堆排序的体会

本文详细介绍了堆排序的基本概念及其实现过程,包括如何构建最小堆或最大堆,并通过调整来完成排序。同时分析了堆排序的时间复杂度,并提供了具体的代码示例。
首先堆排序要承认几个事实:
1. 数组已经给你,相当于一颗完全二叉树已经给出。只是这棵二叉树是以数组形式存储。
2. 结点之间的关系:结点i的孩子的下标是2*i+1和2*i+2(如果有右孩子的话)。
3. 完全二叉树的性质:一个非叶子结点只有一个左孩子或者有两个孩子。
4. 如果以最小堆建堆,最后的数组排序输出结果是倒序(从大到小)
5. 建堆的概念:不是一个一个结点插入堆中。而是一个堆已经给出,我们需要把它调整成最小堆或最大堆。
6. 完全二叉树的最后一个结点的父亲的下标为n/2-1.(数组以0开始,n为数组的长度。)


堆排序的思想:
1. 下标为i=n/2-1的元素开始向下调整,保证以此结点为跟结点的子树满足最小堆的性质。
2. 调整:如果父节点大于两孩子结点的某一个p,则父节点与p交换。然后沿着p往下走。

3. i--;重复步骤1,直到下标为0.




堆排序的性能分析:
建堆需要O(n)。之后进行n-1次向下调整操作,每次调整的时间为O(h)。由于是完全二叉树,所以时间复杂度始终为O(n*logn)。与
数组的初试状态无关。

堆排序是不稳定排序。


void Swap(int &a, int &b){
	int temp=a;
	a=b;
	b=temp;
}
void AdjustDown(int A[], int s,int n){//注意这里的n是数组的长度,不是数组最后一个元素的下标。
	int min;
	for(int i=s;(2*i+1)<n;){
		if(2*i+2<n && A[2*i+1]>A[2*i+2])//沿较小的子节点向下调整
			min=2*i+2;
		else min=2*i+1;
		if(A[i]<=A[min]) break;//调整结束
		Swap(A[i],A[min]);     
		i=min;//沿较小的子节点向下走
	}
}
void BuildHeap(int A[], int n)
{
	for(int i=n/2-1;i>=0;i--)
		AdjustDown(A,i,n);
}
void HeapSort(int A[], int n){
	BuildHeap(A,n);
	for(int i=n-1;i>0;i--){
		Swap(A[0],A[i]);
		AdjustDown(A,0,i);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值