前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【数据结构】八大排序之堆排序算法

【数据结构】八大排序之堆排序算法

作者头像
修修修也
发布2024-04-01 16:08:18
1200
发布2024-04-01 16:08:18
举报

一.堆排序简介及思路

堆排序(Heap Sort)是一种效率较高的选择排序算法. 它是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它通过堆来进行选择数据.

有关还不了解的朋友可以先移步这篇文章:【数据结构】什么是堆?

它的基本思想是:

  1. 将待排序的序列构造成一个大堆.(如果是降序则建小堆)
  2. 此时,整个序列的最大值就是堆顶的根结点.将它移走(其实就是我们前面堆实现中的出堆顶操作).
  3. 然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次小值(即堆顶).
  4. 如此反复执行,就可以得到一个有序的序列了.

算法动图演示: 1.向下调整建堆 逻辑结构:

物理结构:

2.堆排序(升序) 逻辑结构:

物理结构:


二.堆排序的代码实现

算法实现步骤:(以升序为例)

  1. 从最后一个叶子结点的双亲节点开始向前遍历并向下调整建堆.
  2. 建堆完成后,将堆顶元素与待排序列的最后一个元素做交换.
  3. 交换后缩小待排序列范围,使刚刚交换到最后的堆顶元素不再参与后续的堆排序.
  4. 重新将新堆顶元素向下调整,使堆恢复为大堆.
  5. 重复2-4步骤,直到数组完全有序.

搞清实现步骤后,代码的实现就比较简单了,堆排序代码如下:

代码语言:javascript
复制
//交换函数
void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

//向下调整建堆
void AdjustDown(int* a, int n, int parent)
{
	int child = parent * 2 + 1;//默认是左孩子
	while (child < n)//孩子走到叶子就可以停止了
	{
		//选出左右孩子中大的那个
		if (child + 1 < n && a[child + 1] > a[child])//如果右孩子存在且大于左孩子
		{
			child++;
		}
		//向下调整重新使堆有序
		if (a[child] > a[parent])//建大堆
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}


//堆排序(升序
void HeapSort(int* a, int n)
{
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)//先向下调整建堆
	{
		AdjustDown(a, n, i);
	}

	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[end], &a[0]);//将堆顶元素和待排区间的最后一个元素交换

		AdjustDown(a, end, 0);

		end--;
	}
}

三.堆排序的时间复杂度分析

堆排序方法对数据数较少的序列排序的效果并不很好,但对n较大的序列还是很有效的. 因为它的运行时间主要耗费在建初始堆和调整建堆时进行的反复"筛选"上. 对深度为k的堆,筛选算法中进行的关键字比较次数至多为2(k-1)次,则在建含n个元素,深度为h的堆时,总共进行的关键字比较次数不超过4n.又因为n个结点的完全二叉树的深度为

\left \lfloor log_{2}n \right \rfloor +1
\left \lfloor log_{2}n \right \rfloor +1

,则调整建新堆时调用向下建堆函数过程n-1次,总共进行的比较次数不超过下式:

2*(\left \lfloor log_{2}(n-1) \right \rfloor +\left \lfloor log_{2}(n-2) \right \rfloor+...+log_{2}2)<2n*(\left \lfloor log_{2}n \right \rfloor)
2*(\left \lfloor log_{2}(n-1) \right \rfloor +\left \lfloor log_{2}(n-2) \right \rfloor+...+log_{2}2)<2n*(\left \lfloor log_{2}n \right \rfloor)

因此,堆排序在最坏的情况下,其时间复杂度也为O(nlogn),这是相对快排,堆排的最大优点.

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-01-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.堆排序简介及思路
  • 二.堆排序的代码实现
  • 三.堆排序的时间复杂度分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com