一、用模版实现大小堆
如果不用模版的话,写大小堆,就需要分别实现两次,但是应用模版的话问题就简单多了,我们只需要实现两个仿函数,Greater和Less就行了,仿函数就是用类实现一个()的重载就实现了仿函数。这个看下代码就能理解了。再设计参数的时候,需要把模版设计成模版的模版参数,因为要实现大小堆嘛!当我们实现好一个大堆或者小队的逻辑后只需要用模版接收的Greater或Less类定义一个变量,就能实现通用功能了。
template<typenameT> structLess { booloperator()(constT&l,constT&r) { returnl<r; } }; template<classT> structGreater { booloperator()(constT&l,constT&r) { returnl>r; } }; template<classT,template<class>classcompare=less> classHeap { public: Heap() {} Heap(T*a,size_tsize) { size_tindex=0; while(index<size) { _a.push_back(a[index]); index++; } for(inti=(_a.size()-2)/2;i>=0;i--) _AdjustDown(i); } voidpush(constT&x) { _a.push_back(x); _AdjustUp(_a.size()-1); } voidpop() { size_tsize=_a.size(); assert(size>0); swap(_a[0],_a[size-1]); _a.pop_back(); size=_a.size(); _AdjustDown(0); } size_ttop() { assert(!_a.empty()); return_a[0]; } boolempty() { return_a.size()==0; } size_tSize() { return_a.size(); } voidPrint() { for(inti=0;i<_a.size();i++) { cout<<_a[i]<<""; } cout<<endl; } protected: void_AdjustUp(intchild) { intparent=(child-1)/2; compare<T>com;//如果是大堆传过来就是用大堆的逻辑,小堆就实现小堆的逻辑 while(child>0) { //找出孩子中的最大孩子 if(com(_a[child],_a[parent])) { swap(_a[child],_a[parent]); child=parent; parent=(child-1)/2; } else { break; } } } void_AdjustDown(size_tparent) { size_tchild=2*parent+1; compare<T>com;//如果是大堆传过来就是用大堆的逻辑,小堆就实现小堆的逻辑 while(child<_a.size()) { //找出孩子中的最大孩子 if(child+1<_a.size()&&com(_a[child+1],_a[child])) { ++child; } //把 if(com(_a[child],_a[parent])) { swap(_a[parent],_a[child]); parent=child; child=child*2+1; } else { break; } } } protected: vector<T>_a; };
二、用模版实现优先级队列
前面实现了大小堆,这里我们可以使用适配器,直接调用大小堆,来实现优先级队列。
template<classT,template<class>classcompare=Less> classpriorityQueue { private: Heap<T,compare>_hp; public: voidpush(constT&x) { _hp.push(x); } voidpop() { _hp.pop(); } T&Top() { return_hp.top(); } voidPrint() { _hp.Print(); } };
三、堆排序的实现
堆排序的实现简单思路,(升序)先构造出来一个大堆,调整堆后,将堆头和最后一个数据交换,最大值就换到了数组的最后,然后在调整堆,但是size需要减少1,因为最大的已经调整到最后,如果再加上它调整又会回到堆头。
int*&HeapSort(int*a,size_tsize) { for(inti=(size-2)/2;i>=0;i--) { _AdjustDown(a,size,i); } for(inti=0;i<size;i++) { swap(a[0],a[size-i-1]); _AdjustDown(a,size-i-1,0); } returna; }