堆排序

堆排序是利用堆这种数据结构设计的一种排序算法,是排序算法中最复杂的一个。本文参考了https://www.cnblogs.com/chengxiao/p/6129630.html,自己对堆排序做一个记录和总结

不稳定排序,最差最好平均的时间复杂度都是O(nlogn)。空间复杂度是O(1)

堆有大顶堆和小顶堆,

大顶堆:每个结点的值都大于等于左右子结点的值称为大顶堆

小顶堆:每个结点的值都小于等于左右子结点的值称为小顶堆

对堆中的结点按层进行编号,映射到数组中如下:

对堆排序的很清晰易懂的演示:https://www.bilibili.com/video/av18980178/

流程就是:

先把输入的数组创建一个大顶堆,此时头结点是最大的

将头结点与尾节点交换,然后在树中删除尾节点(即删除了最大的数),此时最大的数排列到了数组的最后面

再对剩下的数创建一个大顶堆,交换头尾结点,并删除尾节点,依次类推,直到最后剩余一个数

这样不断地 创建大顶堆,交换头结点,删除最大数,最终得到一个从小到大的排序数组。注意删除并不是实际意义上的删除,只是在堆中排除这个数,在调整大顶堆的时候忽略这个数。

//堆化,即调整成最大堆
void heapify(int a[], int start, int end)
{
	int dad = start;
	int son = dad * 2 + 1;  //dad的左子结点
	while (son <= end)  //结点下标在范围内
	{
		//比较左右节点,选择大的那个与父结点比较
		if (son + 1 <= end && a[son] < a[son + 1]) //如果左子结点小于右子结点,son指向右子结点
			son++;
		if (a[dad] > a[son])   //如果父结点大于子结点,不需要调整,返回
			return;
		else //如果父结点小于子结点,交换父子结点,然后继续比较子孙结点
		{
			swap(a[dad], a[son]);
			dad = son;
			son = dad * 2 + 1;
		}
	}
}

//实现堆排序
void heapSort(int a[], int len)
{
	//1、构建大顶堆
	//从最后一个父结点开始调整成大顶堆,从下往上,从左往右
	for (int i = len / 2 - 1; i >= 0; i--)
		heapify(a, i, len - 1);
	//2、交换顶结点与尾节点,再对剩下的数构建大顶堆
	//循环利用i--  把交换后的尾节点删除,实际上没删除!
	for (int i = len - 1; i > 0; i--) 
	{
		swap(a[0], a[i]);    //交换顶结点与尾节点
		heapify(a, 0, i - 1);  //表示删除了尾节点,再对剩下的数调整成大顶堆
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值