堆排序(Heap Sort)

        堆排序就是利用堆(假设利用大顶堆)进行排序的方法。它的基本思想是,将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆的根结点。将它移走(其实就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值),然后将剩余n-1个序列重新构造成一个堆,这样就会得到n个元素中的次小值。如此反复执行,便能得到一个有序序列了。

代码如下:

#include <iostream>
using namespace std;

void Swap(int *L, int i, int j)  
{  
	int temp = L[i];  
	L[i] = L[j];  
	L[j] = temp;  
}  

void HeapAdjust(int *L, int s, int m)
{
   int temp,j;
   temp = L[s];
   for (j=2*s;j<=m; j *= 2)
   {
	   if (j<m && L[j]<L[j+1])
	   {
		   ++j;
	   }
	   if (temp >= L[j])
	   {
		   break;
	   }
	   L[s] = L[j];
	   s = j;
   }
   L[s] = temp;
}

void HeapSort(int *L, int n)
{
	int i;
	for(i=n/2; i>0; i--)//step1:构造大顶堆
		HeapAdjust(L,i,n);
	for (i=n; i>1; i--)//step2:取出最大元素,调整剩下的元素为堆
	{
		Swap(L,1,i);//将堆顶记录和当前未经排序子序列的最后一个记录交换
		HeapAdjust(L,1,i-1);//将l[1...i-1]重新调整为大顶堆
	}
}

int main()
{
    int L1[10] = {-1,9,1,5,8,3,7,4,6,2};//堆的编号从1到n(9),所以0号元素存-1,表无效数据。
	int L2[10] = {-1,50,10,90,30,70,40,80,60,20};
    HeapSort(L2,9);//n=9
	for (int i = 1; i<=9; i++)
	{
		cout<<L2[i]<<" ";
	}
	cout<<endl;
	getchar();
	return 0;
}

结果:

        堆排序的运行时间主要是消耗在初始构建堆和在重建堆时的反复筛选上。

        在构建堆的过程中,因为我们是完全二叉树从最下层最右边的非终结点开始构建,将它与其孩子进行比较和若有必要的互换,对于每个非终结点来说,其实最多进行两次比较和互换操作,因此整个构建堆的时间复杂度为O(n).

        在正式排序时,第i次取堆顶记录重建堆需要用O(logi)的时间(完全二叉树的某个节点到根节点的距离为),并且需要取n-1次堆顶记录,因此重建堆的时间复杂度为O(N*logN)。

        所以总体来说,堆排序的时间复杂度为O(N*logN)。由于堆排序对原始记录的排序状态并不敏感,因此它无论最好、最坏和平均时间都是O(N*logN)。这在性能上显然要远远好于冒泡、简单选择、直接插入的O(n^2)时间复杂度了。

小顶堆可参考:

白话经典算法系列之七 堆与堆排序


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值