C++ STL中提供了不少和排序相关的算法,包括堆排序(heap_sort)、排序(sort)、稳定排序(stable_sort)、局部排序(partial_sort),时间复杂度均为O(nlogn)。其中,对于堆排序,也提供了不少函数,像入堆push_heap、创建堆make_heap、出堆pop_heap,是否为堆is_heap等。首先要明确数据结构上堆的概念。对于一个迭代器区间上的元素,不管实际的数据结构如何,都可以逻辑上排成一个完全二叉树,如果树的每个父节点都不小于左右两个子节点,那么区间元素就构成了一个堆。例子很简单,算是科普性的。。。
入堆push_heap算法带有二元谓词判断comp,可以自行设定元素的大于或者小于关系,从而进一步确定创建的是大根堆还是小根堆。其函数原型对应两种,
template <class RandomAccessIterator> void push_heap (RandomAccessIterator first, RandomAccessIterator last); template <class RandomAccessIterator, class Compare> void push_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
第一种方式默认创建的是大根堆。
Given a heap in the range [first,last-1),this function extends the range considered a heap to [first,last) by placingthe value in (last-1) into its corresponding location within it.
#include<iostream> #include<algorithm> #include<vector> using namespace std; void print(int x) { cout<<x<<" "; } int main() { vector<int> v; v.push_back(38); v.push_back(11); v.push_back(15); v.push_back(39); v.push_back(60); v.push_back(55); v.push_back(20); v.push_back(26); make_heap(v.begin(),v.end()); for_each(v.begin(),v.end(),print); cout<<endl; return 0; }
创建堆make_heap算法重新排列元素,使元素在逻辑上构成一个堆,默认是大根堆。函数原型有两种:
template <class RandomAccessIterator> void make_heap (RandomAccessIterator first, RandomAccessIterator last); template <class RandomAccessIterator, class Compare> void make_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp );
Rearranges the elements in the range[first,last) in such a way that they form a heap.
#include<iostream> #include<algorithm> #include<vector> using namespace std; void print(int x) { cout<<x<<" "; } int main() { vector<int> v; v.push_back(38); v.push_back(11); v.push_back(15); v.push_back(39); v.push_back(60); v.push_back(55); v.push_back(20); v.push_back(26); make_heap(v.begin(),v.end()); for_each(v.begin(),v.end(),print); cout<<endl; return 0; }
相对于push_heap,pop_heap将元素进行出堆操作。
实现过程大概是这样的,将已经够成堆的迭代器区间中的最大值元素即根节点,移动到最后元素位置,原来的最后元素调整为根节点后,再对区间元素重新创建堆。
函数原型有两个:
template <class RandomAccessIterator> void push_heap (RandomAccessIterator first, RandomAccessIterator last); template <class RandomAccessIterator, class Compare> void push_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
#include<iostream> #include<algorithm> using namespace std; void print(int x) { cout<<x<<" "; } int main() { int iArray[]={1,2,3,4,5}; const int len=sizeof(iArray)/sizeof(int); cout<<"创建堆"<<endl; make_heap(iArray,iArray+len); for_each(iArray,iArray+len,print);//5 4 3 2 1 cout<<endl; cout<<"出堆一次"<<endl; pop_heap(iArray,iArray+len); for_each(iArray,iArray+len,print);//4 3 2 1 5 return 0; }
利用堆进行排序,时间复杂度为O(nlogn)。
#include <algorithm> #include <vector> #include <iostream> using namespace std; void print(int x){ cout << x << ' '; } int main(void){ vector<int> v; v.push_back(3); v.push_back(9); v.push_back(6); v.push_back(3); v.push_back(12); v.push_back(17); v.push_back(20); for_each(v.begin(), v.end(), print); cout << endl; //建立堆 make_heap(v.begin(), v.end()); cout<<"创建堆,未排序之前"<<endl; for_each(v.begin(),v.end(),print); cout<<endl; //堆排序 cout << "进行堆排序" << endl; sort_heap(v.begin(), v.end()); for_each(v.begin(), v.end(), print); cout << endl; return 0; }