用仿函数实现大小堆及堆排序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用仿函数实现大小堆及堆排序相关的知识,希望对你有一定的参考价值。
"2.h" #include<iostream> #include<vector> #include<assert.h> using namespace std; template<class T> struct Less { bool operator()(const T& left,const T& right) { return left<right; } }; template<class T> struct Greater { bool operator()(const T& left,const T& right) { return left>right; } }; template<class T,class Compare=Less<T>>//小堆//修改 class Heap { public: Heap(); Heap(const T* a,size_t size); void Push(const T& x); void Pop(); T& Top(); void Print(); void HeapSort(); void HeapSort1(); protected: void AdjustDown(int parent); void AdjustUp(int child); void _AdjustDown(int child,int size); protected: vector<T> _array; Compare _compare; }; template<class T,class Compare> Heap<T,Compare>::Heap(const T* a,size_t size) { for(size_t i=0;i<size;i++) { _array.push_back(a[i]); } for(int i=(_array.size()-2)/2;i>=0;i--)//求父节点的下标为:((子-1)/2),而size()比最大下标多一,所以为减2 { AdjustDown(i); } /*for(int i=_array.size()-1;i>0;i--) { AdjustUp(i); }*/ } template<class T,class Compare> void Heap<T,Compare>::AdjustDown(int parent) { int child=parent*2+1; while(child<_array.size()) { if((child+1<_array.size())&&_compare(_array[child+1],_array[child]))//右孩子是否越界条件易忘 swap(_array[child],_array[child+1]); if(Compare()(_array[child],_array[parent])) { swap(_array[child],_array[parent]); parent=child; child=parent*2+1; } else break; } } template<class T,class Compare> void Heap<T,Compare>::AdjustUp(int child) { int parent=(child-1)/2; while(child>0)//条件不能写成parent>=0,因为parent不可能小于0 { if(child+1<_array.size()&&_compare(_array[child+1],_array[child])) swap(_array[child],_array[child+1]); if(Compare()(_array[child],_array[parent])) { swap(_array[child],_array[parent]); child=parent; parent=(child-1)/2; } else break; } } //插进来的放在最后的子节点位置 template<class T,class Compare> void Heap<T,Compare>::Push(const T& x)//记住加上const和& { _array.push_back(x); //AdjustDown(0); //想清楚可不可用AdjustDown(0); //不可以,主要看哪儿动了 AdjustUp(_array.size()-1); } //Pop出去的是根,下标为0 template<class T,class Compare> void Heap<T,Compare>::Pop() { // swap(_array[0],_array[_array.size()-1]); _array.pop_back(); AdjustDown(0); } template<class T,class Compare> T& Heap<T,Compare>::Top() { return _array[0]; } template<class T,class Compare> void Heap<T,Compare>::Print() { for(size_t i=0;i<_array.size();i++) { cout<<_array[i]<<" "; } cout<<endl; } //把堆排成大堆,交换堆顶和堆尾,每次除掉堆尾数据其余数据继续排成大堆... //理解错误,虽然能实现堆排序,但误用AdjustUp(int child)(没去掉注释的两行)——向上排序只用于已排好二叉树进行插入时,少数数据的改变,不能在构造函数中直接用向上排序构造template<class T,class Compare> void Heap<T,Compare>::HeapSort() { for(int i=_array.size()-1;i>=0;i--) { for(int j=_array.size()-1;j>0;j--)//除掉堆尾数据有误 AdjustUp(j); swap(_array[0],_array[i]); } } //由于要改变size,所以得重建AdjustDown template<class T,class Compare> void Heap<T,Compare>::HeapSort1() { for(int size=_array.size();size>1;size--) { for(int i=(size-2)/2;i>=0;i--) { _AdjustDown(i,size); } swap(_array[0],_array[size-1]); } } template<class T,class Compare> void Heap<T,Compare>::_AdjustDown(int parent,int size) { int child=parent*2+1; while(child<size) { if((child+1<size)&&_compare(_array[child+1],_array[child])) swap(_array[child],_array[child+1]); if(Compare()(_array[child],_array[parent])) { swap(_array[child],_array[parent]); parent=child; child=parent*2+1; } else break; } } #include "2.h" #include<iostream> using namespace std; void Test1() { int a[]={1,2,9,5,8,7,4,3}; //Heap<int> hp1(a,8); Heap<int,Greater<int>> hp1(a,8); hp1.Print(); hp1.Push(0); hp1.Print(); hp1.Pop(); hp1.Print(); int top=hp1.Top(); cout<<top<<endl; hp1.HeapSort(); hp1.Print(); } int main() { Test1(); system("pause"); return 0; }
本文出自 “sunshine225” 博客,请务必保留此出处http://10707460.blog.51cto.com/10697460/1758170
以上是关于用仿函数实现大小堆及堆排序的主要内容,如果未能解决你的问题,请参考以下文章