堆排序精讲

堆排序是一种基于堆数据结构的排序算法,时间复杂度为O(n*logn)。它包括建堆、交换堆顶与末尾元素、重新调整堆的过程。建堆有向下调整和向上调整两种方法。文章提供了降序排列的堆排序代码实现,并通过示例进行了测试。
摘要由CSDN通过智能技术生成

堆排序的时间复杂度是n*logn,可以说吊打冒泡排序(n^2)。是建立在堆这种数据结构的理解上演化出来的一种排序方式。上篇文章对堆这种数据结构已经有详细的介绍。这篇文章就用堆这种数据结构基础搞定堆排序。

 一.堆排序思路

堆排序的思路是:若排降序,将给定数据(数组中)建小堆,因为小堆堆顶数据一定最小,每次互换堆顶元素和最后一个元素,将最后一个元素分隔开,然后从堆顶开始向下调整,继续互换堆顶元素和倒数第二个元素,再将倒数第二个分隔开,再从堆顶向下调整,循环这个过程,直到只剩下一个元素为止。若排升序,则建大堆,后续相同。

二.建堆 

堆的存储结构是数组,逻辑结构是完全二叉树。要想实现堆排序,首先需要建堆这里提供两种建堆方法:

一.向下调整建堆

first step,找到尾节点的父亲节点

注:灰色数字为数组中的下标

 second step,从这个节点开始向下调整,下标顺序为:3->2->1->0

注:红色的数字为向下调整顺序:1->2->3->4

二.向上调整建堆

向下调整建堆的本质就是依次将数据插入堆

 插入顺序为:1->2->3->4->5->6->7->8

 每次向上调整,将数据一个一个插入堆。可保证最后是一个堆。

三.排序(这里是降序)

降序需要建小堆,排序的逻辑就是每次交换堆顶元素和堆尾(下标为end)元素,分离堆尾元素。

交换完毕后,将堆顶元素向下调整,重新建堆,堆顶元素又成为剩下数据中的最小数据,再交换堆顶元素和堆尾元素(下标为end),再分离,循环往复,直到堆里只整下一个元素。

四.代码实现及测试

void swap(int* pa, int* pb)//交换函数
{
	int tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}
void AdjustDown(int* a, int size, int parent)//建小堆的向下调整
{
	int child = parent * 2 + 1;//左孩子
	while (child<size)
	{
		if (child+1<size&&a[child] > a[child + 1])//找到较小的孩子
			child++;

		if (a[parent] >a[child])
		{
			swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}
int main()
{
	int a[7] = {2,4,5,7,6,8,9};//想要排降序
	//建小堆
	int end = 6;//堆尾下标
	int parent = (end - 1) / 2;//堆尾节点的父亲节点下标
	while (parent >= 0)
	{
		AdjustDown(a, 7, parent);//这里用向下调整建堆
		parent--;
	}
    //排序
	while (end > 0)//直到堆里只剩下最后一个数据
	{
		swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		end--;
	}
    //测试
	for (int i = 0; i < 7; i++)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

代码测试结果

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无极太族

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值