堆排序

1.什么是堆?

堆的定义:堆是一棵完全二叉树按照顺序存储方式得到的一个数组,且满足父节点的值大于左右孩子结点的值。(大根堆)

2.维护大根堆的性质

假定:以数组A中第i个元素的左孩子、右孩子为跟结点的二叉树满足大根堆的要求,若A[i]小于其孩子的值,则违背大根堆的要求。

解决方法: 
(1)找出A[i]、其左孩子、右孩子的最大值,下标为largest。 
(2)如果largest == i,表明结点i满足大根堆要求,结束; 
如果largest != i,表明结点i不满足大根堆要求,交换A[largest]与A[i],这样largest位置上的值是A[i],有可能以largest为根的结点违背大根堆的要求,这样的话,继续递归向下调整largest结点。

代码如下:

//维护大根堆的性质,从第i个元素向下调整
//其假定是,以当前结点i的左孩子、右孩子为根结点的二叉树是大根堆。
//len表示最后一个元素的下标。
void maxHeapify(int A[],int len, int i)
{
	//找到当前节点i,左孩子、右孩子 的最大值的下标
	int left = i * 2;
	int right = i * 2 + 1;
	int largest = i;
	if (left <= len && A[left] > A[i])
		largest = left;
	if (right <= len && A[right] > A[largest])
		largest = right;

	//如果A[i]最大,则结束,否则交换A[largest]与A[i],然后递归
	if (i != largest)
	{
		int temp = A[i];
		A[i] = A[largest];
		A[largest] = temp;

		maxHeapify(A,len,largest);
	}	
}

3. 建立大根堆

用自底向上的方法利用过程maxHeapify,把数组转化为大根堆。数组的len/2之后的元素为叶结点,每个叶结点看作是只包含一个元素的堆。这样的话对其余结点依次调用maxHeapify便可。 
代码如下:

//自底向上建堆,叶子结点已经是一个堆了,故从i=len/2开始调整。
void buildheap(int A[],int len)
{
	for(int i = len/2; i >= 1; i--)
	{
		maxHeapify(A,len,i);
	}
}

4.堆排序

堆排序:建好堆以后,交换第一个和最后一个元素,则最后的是最大数。如果从堆中去掉最后一个元素,使size减1,重新调整大根堆maxHeapify(A[],len, 1),再交换第一个和最后一个元素,以此类推,直到堆的size为1,结束。 
代码如下:

void heapsort(int A[], int len)
{
	buildheap(A,len);

    for(int i = len; i>1; i--)
	{
	  //交换换第一个和最后一个元素,size减1
	  int temp = A[1]; A[1] = A[i];A[i]= temp;
	  //调整大根堆
	  maxHeapify(A,i,1);
	}
}


 

测试代码如下:

#include <iostream>
using namespace std;

int main()
{
	int A[] = {0,3,2,9,7,1};
	//len表示最后一个元素的下标。
	heapsort(A,5);
	for(int i = 1; i<6; i++)
		cout<<A[i]<<" ";
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值