数据结构与算法分析-C++描述 第7章 堆排序(heapSort)

堆排序(heapSort):

        使用优先队列的方法,第一步建立N个元素的二叉堆,总共花费O(N)时间,删除每个元素花费O(\log N)时间,则完成一次输出最小值总计花费O(N\log N)时间,堆排序给出了至今所见的最佳大O运行时间。

      为了节省空间,可将删除的元素重新放回数组队尾,对于最小堆而言,最终的输出结果将是降序排列,为了习惯升序排序方式,需建立最大堆(最小堆),然后将“删除”根节点,放置v[N-1]处,进行下溢处理,依次删除根节点,最终的输出为升序排列结果。

行为描述:输入31, 41, 59, 26,53, 58,97时建立的二叉堆(每个父亲节点处判断下溢操作)【注:此时下标从0开始】

删除根节点:

 

 算法描述:第一步建立N个元素的二叉堆,第二步删除根节点并填充到数组队尾;

堆排序的性质:

       第一阶段构建堆最多用2N次比较;

       第二阶段第i次删除最大值最多用到2\left \lceil \log i \right \rceil次比较,总数最多为2N\log N-O(N)次比较,因此最坏情况下堆排序最多使用2N\log N-O(N)次比较。

        定理:N个互异项随机排列的堆排序,所用比较的平均次数为2N\log N - O(N \log \log N)

堆排序实例:

//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 !

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值