螺丝和螺帽Nuts and bolts 《算法》2.3.15

来源:互联网 发布:卓有成效的管理者知乎 编辑:程序博客网 时间:2024/05/16 01:08
Sedgewick 算法第四版
习题2.3.15 螺丝和螺帽:
                  “(G.J.E.Rawlins)假设有N个螺丝和N个螺帽混在一堆,你需要快速将它们配对。一个螺丝只会匹配一个螺帽,一个螺帽也只会匹配一个螺丝。你可以试着把一个螺丝和一个螺帽拧在一起看看谁大了,但不能直接比较两个螺丝或者两个螺帽。给出一个解决这个问题的有效方法。”


思路一:将quick sort略加改变。
quick sort原版是通过和一个pivot值比较,将待排序数组分为两个部分,在子数组中继续选一个pivot,这样递归地排序。这里的问题是只能比较螺丝和螺帽,所以应该改变比较的方式。
步骤:
   1)将螺丝螺帽分开。可以转化成一个只有两种值的数组的排序问题,这里不深究。
   2)选一个螺丝(也可以螺帽,之后反过来就行),以此螺丝为pivot,将螺帽分两组。
   3)以步骤2中的螺丝对应的螺帽为pivot,将螺丝分为两组
   4)经过步骤2和3,螺丝螺帽已经被分为大小两个组,然后递归地进行步骤2,3即可

#pragma once#include <memory>#include <ctime>#include <random>#include <iostream>class Nuts_And_Bolts {struct Nut{Nut(int s);int size;};struct Bolt{Bolt(int s);int size;};friend bool operator<(const Nuts_And_Bolts::Nut & n, const Nuts_And_Bolts::Bolt & b);friend bool operator>(const Nuts_And_Bolts::Nut & n, const Nuts_And_Bolts::Bolt & b);friend bool operator==(const Nuts_And_Bolts::Nut & n, const Nuts_And_Bolts::Bolt & b);friend bool operator<(const Nuts_And_Bolts::Bolt & b, const Nuts_And_Bolts::Nut & n);friend bool operator>(const Nuts_And_Bolts::Bolt & b, const Nuts_And_Bolts::Nut & n);friend bool operator==(const Nuts_And_Bolts::Bolt & b, const Nuts_And_Bolts::Nut & n);std::allocator<Bolt> bolt_alloc;std::allocator<Nut> nut_alloc;public:Nuts_And_Bolts(int n);//n个螺丝和n个螺帽一一配对,假设已经分成两堆,从小到大排列~Nuts_And_Bolts();void shuffle();//将螺丝和螺帽分别打乱void show();//按在数组中的顺序组成pair并打印出来Bolt* bolts;//Bolts堆Nut* nuts;//Nuts堆int size;//等于n};void sort(Nuts_And_Bolts& nb);//好名字。。。

#include "exercise2.3.15.h"bool operator<(const Nuts_And_Bolts::Nut & n, const Nuts_And_Bolts::Bolt & b){return n.size<b.size;}bool operator>(const Nuts_And_Bolts::Nut & n, const Nuts_And_Bolts::Bolt & b){return n.size>b.size;}bool operator==(const Nuts_And_Bolts::Nut & n, const Nuts_And_Bolts::Bolt & b){return n.size == b.size;}void sort_impl(Nuts_And_Bolts& nb, int lo, int hi){if (lo >= hi)return;//以bolts[lo]为pivot,对nuts排序//双指针,两头向中间扫描并交换的快排int beg = lo;int end = hi;auto pivot_b = nb.bolts[lo];using std::swap;while (true) {while (beg <= hi&&nb.nuts[beg] < pivot_b) {++beg;}while (end >= lo&&nb.nuts[end] > pivot_b) {--end;}if (beg > end) {//将在lo中存放的匹配的nut放到合适的位置swap(nb.nuts[lo], nb.nuts[--beg]);break;}if (beg == end) {break;}if (nb.nuts[beg] == pivot_b || nb.nuts[end] == pivot_b) {//如果遇见了匹配的nutif (nb.nuts[beg] == pivot_b) {//将匹配的nuts暂时放到loif (beg == lo) {//如果beg本来就是lo就会导致死循环++beg;}else {swap(nb.nuts[lo], nb.nuts[beg]);}}else {swap(nb.nuts[end], nb.nuts[lo]);}//beg,end不移动以待下一轮处理}else {//如果没有遇见匹配的nutswap(nb.nuts[beg], nb.nuts[end]);++beg;--end;}}//通过pivot_b将nuts排完了序//现在通过pivot_n将bolt排序auto pivot_n = nb.nuts[beg];beg = lo;end = hi;while (true) {while (beg <= hi&&nb.bolts[beg] < pivot_n) {++beg;}while (end >= lo&&nb.bolts[end] > pivot_n) {--end;}if (beg > end) {//将在lo中存放的匹配的nut放到合适的位置swap(nb.bolts[lo], nb.bolts[--beg]);break;}if (beg == end) {break;}if (nb.bolts[beg] == pivot_n || nb.bolts[end] == pivot_n) {//如果遇见了匹配的nutif (nb.bolts[beg] == pivot_n) {//将匹配的nuts暂时放到loif (beg == lo) {//如果beg本来就是lo就会导致死循环++beg;}else {swap(nb.bolts[lo], nb.bolts[beg]);}}else {swap(nb.bolts[end], nb.bolts[lo]);}//beg,end不移动以待下一轮处理}else {//如果没有遇见匹配的nutswap(nb.bolts[beg], nb.bolts[end]);++beg;--end;}}//现在bolts也排了序//beg是匹配的位置sort_impl(nb, lo, beg - 1);sort_impl(nb, beg + 1, hi);}void sort(Nuts_And_Bolts & nb){nb.shuffle();//打乱以保证快排效率sort_impl(nb, 0, nb.size - 1);}bool operator<(const Nuts_And_Bolts::Bolt & b, const Nuts_And_Bolts::Nut & n){return b.size<n.size;}bool operator>(const Nuts_And_Bolts::Bolt & b, const Nuts_And_Bolts::Nut & n){return b.size>n.size;}bool operator==(const Nuts_And_Bolts::Bolt & b, const Nuts_And_Bolts::Nut & n){return b.size==n.size;}Nuts_And_Bolts::Nut::Nut(int s) :size(s){}Nuts_And_Bolts::Bolt::Bolt(int s) : size(s){}Nuts_And_Bolts::Nuts_And_Bolts(int n){bolts = bolt_alloc.allocate(n);nuts = nut_alloc.allocate(n);for (int i = 0; i < n; ++i) {//从0到n-1,螺丝螺帽一一配对,已经从小到大排序好bolt_alloc.construct(bolts + i, i);nut_alloc.construct(nuts + i, i);}size = n;}Nuts_And_Bolts::~Nuts_And_Bolts(){for (int i = 0; i < size; ++i) {bolt_alloc.destroy(bolts + i);nut_alloc.destroy(nuts + i);}bolt_alloc.deallocate(bolts, size);nut_alloc.deallocate(nuts, size);}void Nuts_And_Bolts::shuffle(){static std::default_random_engine rgen(time(nullptr));static std::uniform_int_distribution<> dis;using std::swap;for (int i = 0; i < size; ++i) {swap(bolts[i], bolts[dis(rgen, decltype(dis)::param_type(0, i))]);swap(nuts[i], nuts[dis(rgen, decltype(dis)::param_type(0, i))]);}}void Nuts_And_Bolts::show(){for (int i = 0; i < size; ++i) {std::cout << " ( " << bolts[i].size << " , " << nuts[i].size << " ) " << std::endl;}std::cout << std::endl;}

    
 
1 0
原创粉丝点击