堆排序(heapSort):
使用优先队列的方法,第一步建立N个元素的二叉堆,总共花费时间,删除每个元素花费时间,则完成一次输出最小值总计花费时间,堆排序给出了至今所见的最佳大运行时间。
为了节省空间,可将删除的元素重新放回数组队尾,对于最小堆而言,最终的输出结果将是降序排列,为了习惯升序排序方式,需建立最大堆(最小堆),然后将“删除”根节点,放置v[N-1]处,进行下溢处理,依次删除根节点,最终的输出为升序排列结果。
行为描述:输入31, 41, 59, 26,53, 58,97时建立的二叉堆(每个父亲节点处判断下溢操作)【注:此时下标从0开始】
删除根节点:
算法描述:第一步建立N个元素的二叉堆,第二步删除根节点并填充到数组队尾;
堆排序的性质:
第一阶段构建堆最多用2N次比较;
第二阶段第次删除最大值最多用到次比较,总数最多为次比较,因此最坏情况下堆排序最多使用次比较。
定理:对个互异项随机排列的堆排序,所用比较的平均次数为。
堆排序实例:
//heapSort.cpp
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int leftChild(int i){
return 2*i + 1;
}
template<class Compareable>
void percDown(vector<Compareable> &v, int i, int n){
int child;
Compareable temp;
for(temp = v[i]; leftChild(i) < n; i = child){
child = leftChild(i);
//find the larger child
if( (child != n -1) && (v[child] < v[child + 1]) ){
child++;
}
//percolate down node
if(temp < v[child]){
v[i] = v[child];
}else{
break;
}
}
v[i] = temp;
}
template<class Compareable>
void heapSort(vector<Compareable> &v){
//stage 1 : setup the heap
for(int i = v.size() / 2 ; i >= 0; i--){
percDown(v, i, v.size());
/*cout << i << " th result : " ;
for(typename vector<int>::iterator itr = v.begin(); itr != v.end(); ++itr){
cout << *itr << " ";
}
cout << endl;*/
}
//stage 2 : swap and percolate down
for(int j = v.size() - 1; j > 0; j--){
swap(v[0], v[j]);
percDown(v, 0, j);
}
}
int main(){
int arr[] = {81, 94, 11, 96, 12, 35, 17, 95, 28, 58, 41, 75, 15};
int len = sizeof(arr) / sizeof(arr[0]);
vector<int> v;
for(int i = 0 ; i < len; i++){
v.push_back(arr[i]);
}
cout << "******* the original data ***********" << endl;
for(typename vector<int>::iterator itr = v.begin(); itr != v.end(); ++itr){
cout << *itr << " ";
}
cout << endl;
cout << "******* the sorted data ***********" << endl;
heapSort(v);
for(typename vector<int>::iterator itr = v.begin(); itr != v.end(); ++itr){
cout << *itr << " ";
}
cout << endl;
cout << " done ." << endl;
return 0;
}
practice makes perfect !