堆排序详解

#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).

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值