首页 > 编程语言 > 详细

堆排序详解

时间:2015-03-27 14:51:35      阅读:320      评论:0      收藏:0      [点我收藏+]
#include<stdio.h>
//交换函数
void swap(int k[], int i, int j)
{
	int temp;
	temp = k[i];
	k[i] = k[j];
	k[j] = temp;
}
//对顺序表k进行堆排序
void HeapAdjust(int k[],int s,int n)
{
	int i,temp;
	
	temp = k[s];
	//之所以从2s开始是因为根据二叉树的性质知2s就是它的左子结点,
	for(i=2*s;i<=n;i*=2)
	{
		//如果右子结点比左的大,那么i+1,目的就是把最大的交给他们的父结点
		if(i<n&&k[i]<k[i+1])
		{
			i++;
		}
		//如果父结点最大,那么直接跳出循环,不用再继续
		if(temp>=k[i])
		{
			break;
		}
		//把比较大的记录赋值给k[s],即父结点
		k[s] = k[i];
		s = i;//将i的值赋给s,在循环过后可以把刚才父结点的值赋给相应的结点
		
	}
	k[s] = temp;
}
void HeapSort(int k[], int n)
{
	int i;
	//这个循环是将k中的数据构成一个大顶堆
	for(i=n/2; i>0; i--)
	{
		HeapAdjust(k,i,n);
	}
	//这个循环的作用是将堆顶记录和数组的最后一个记录交换,
	//然后再减去1(即最后一个已经是最大的,不用参与)后再重新调整为大顶堆
	for(i=n; i>1; i--)
	{
		swap(k,1,i);//交换第一个和最后一个记录
		HeapAdjust(k,1,i-1);//在没有最后一个记录的情况下重新构造大顶堆
	}
}
int main(){
	int i,a[10] = {-1,5,2,6,0,3,9,1,7,4};
	
	HeapSort(a,9);
	
	printf("排序后的结果是:");
	for(i=1; i<10; i++)
	{
		printf("%d",a[i]);
	}
	
	printf("\n\n");
	
	return 0;
	
}

堆排序复杂度分析:

他的运行时间主要是消耗在初始构建堆和重构建堆时的反复筛选上,在堆的过程中,因为我们是完全二叉树从最下层最右边的非终端结点开始构建,将它与其他孩子进行比较和若有必要的交换,对于每个非终端结点来说,其实最多进行两次比较和互换操作,因此整个构建堆的时间复杂度为O(n),在正式排序的时候,第i次取堆顶记录重建堆需要用O(logi)的时间,并且需要取n-1次堆顶记录,因此,重建堆的时间复杂度为O(nlogn)。

所以,总体来讲,堆排序的时间复杂度为O(nlogn)。由于堆排序对原始记录的排序状态并不敏感,因此,他无论最好最坏和平均时间复杂度都是O(nlogn).

因为他的记录交换和比较是跳跃式进行的,因此堆排序也是一种不稳定的排序方法。

堆排序详解

原文:http://blog.csdn.net/chencangui/article/details/44675597

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!