排序算法之堆排序

本文详细介绍了堆排序的原理,通过实例演示了排序过程,并提供了相应的代码实现,最后进行了总结,帮助读者全面掌握堆排序这一经典算法。

原理:

有N个元素,从层数最多的根节点开始,从右到左逐层向上,不断的构造一个大根堆,当最上层的根为最大的元素的时候,和这个树最后一个子节点交换。然后在对N-1个元素继续构造大根堆。

举例:

   0    1   2    3   4    5    6     7     8     9   (下标)
 1255723190329576


对应转换成树形结构:


为了方便我之后用数组表示了:

从根2的开始:比较根的左右子节点95大于76,且95大于2,95和2进行交换。

12,5,57,95,31,90,32,,2,76

从根57的开始:90大于32且大于根,90与57进行交换。

12,5,90,95,31,57,32,2,76

从根5的开始:95大于31且大于根,90和5进行交换。

12,95,90,5,31,57,32,2,26

从根5的开始:76大于2且大于根,76和5进行交换。

12,95,90,76,31,57,32,2,5

从根12的开始:95大于90且大于根,95和12进行交换。

95,12,90,76,31,57,32,2,5

从根12的开始:76大于31且大于根,76和12进行交换。

95,76,90,12,31,57,32,2,5

从根12的开始:5大于2且小于根,不进行交换。

95,76,90,12,31,57,32,2,5

此时95为最大的根,95和最后的一片叶子节点进行交换。95不再参与堆排序。剩下的元素继续堆排序。

5,76,90,12,31,57,32,2,95

从根12的开始,2小于根。不交换。
从根90的开始,57大于32小于根。不交换。
从根76的开始,31大于12小于根。不交换。
从根5的开始,90大于76且大于根。90和5进行交换。

90,76,5,12,31,57,32,2,95

从根5的开始,57大于32且大于根,57和5进行交换。

90,76,5,12,31,57,32,2,95

此时90为最大的根,90和最后的一片叶子节点进行交换。90不再参与堆排序。剩下的元素继续堆排序。

2,76,5,12,31,57,32,9095

从根5的开始,57大于32且大于根,57和5进行交换。

2,76,57,12,31,5,32,9095

从根76的开始,31大于12且小于根。不交换。
从根2的开始,76大于57且大于根。76和2进行交换。

76,2,57,12,31,5,32,9095

从根2的开始,31大于12且大于根。31和2进行交换。

76,31,57,12,2,5,32,9095

此时76为最大的根,76和最后的一片叶子节点进行交换。76不再参与堆排序。剩下的元素继续堆排序。

32,31,57,12,2,5,769095

从根57的开始,5小于根。不交换。
从根31的开始,12大于2且小于根。不交换。
从根32的开始,57大于31且大于根。57和32进行交换。

57,31,32,12,2,5,769095

从根32的开始,5小于根,不交换。
此时57为最大的根,57和最后的一片叶子节点进行交换。57不再参与堆排序。剩下的元素继续堆排序。

5,31,32,12,2,57769095

从根31的开始,12大于2且小于根,不交换。
从根5的开始,32大于31且大于根,32和5进行交换。

32,31,5,12,2,57769095

此时32为最大的根,32和最后的一片叶子节点进行交换。32不再参与堆排序。剩下的元素继续堆排序。

2,31,5,12,3257769095

从根31的开始,12小于根不交换。
从根2的开始,31大于5且大于根,31和2进行交换。

31,2,5,12,3257769095

从根2的开始,12大于根,12和2进行交换。

31,12,5,2,3257769095

此时31为最大的根,31和最后的一片叶子节点进行交换。31不再参与堆排序。剩下的元素继续堆排序。

2,12,5,313257769095

从根2的开始,12大于5且大于根,12和2进行交换。

12,2,5,313257769095

此时12为最大的根,12和最后的一片叶子节点进行交换。12不再参与堆排序。剩下的元素继续堆排序。

5,2,12313257769095

从根5的开始,2小于根。不交换。
此时5为最大的根,5和最后的一片叶子节点进行交换。5不再参与堆排序。

2,512313257769095

代码:

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

void HeapSort(int a[], int nlen)
{
	
	for (int i = nlen / 2; i > 0; --i)
	{
		HeapAdjust(a, i, nlen);
	}
	for (int i = nlen; i > 1; --i)
	{
		a[1] ^= a[i];
		a[i] ^= a[1];
		a[1] ^= a[i];
		HeapAdjust(a, 1, i-1);
	}
}

总结:

堆排序是不稳定的排序算法,时间复杂度应该为重建堆加调整堆,时间复杂度为O(Nlog2N)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值