在上一篇文章中,我们解释了二叉堆。现在的堆排序算法主要依赖于二叉堆。如果你不知道什么是二叉堆,可以看一下:
【算法与数据结构】什么是二叉堆?
使用辅助数组实现堆排序算法
如果给你一个二叉堆,根据二叉堆的特点,你会如何利用二叉堆来实现堆排序呢?
我们都知道二叉堆有一个非常特殊的节点——堆顶。堆顶要么是所有节点中最大的元素,要么是最小的元素。这主要取决于二叉堆是最小堆还是最大堆。
今天我们暂时选择以最小堆为例。
根据堆顶的特点,我们就可以实现我们的堆排序了。
让我们看一下下面的例子:
对于具有10 个节点元素的二叉堆,如下所示:
我们删除堆顶的节点,然后将删除的节点放到一个辅助数组help中。
显然,被删除的节点是堆中最小的节点。接下来我们继续删除二叉堆的顶部,然后将删除的元素存储到help数组中。
显然,第二次删除的节点是原二叉堆中第二小的节点。
继续删除
继续连续删除堆顶6次,将删除的节点一次一个放入help数组中。
二叉堆中只剩下最后一个节点了。该节点也是原二叉堆中最大的节点。该节点被删除或放入帮助数组中。
此时,二叉堆的所有元素都已被删除。看一下帮助数组。这是一个有序数组。事实上,通过从二叉堆的顶部逐一取出最小值,并将其存储到另一个辅助数组中,当二叉堆耗尽时,我们就完成了一次堆排序。
其实不需要辅助数组
在上面的堆排序过程中,我们使用了辅助数组的帮助。但事实上,我们真的需要辅助数组吗?
我们在上一篇文章讲二进制堆的时候也讲过。二叉堆实现时,是以数组的形式存储的。
要从二叉堆中删除一个元素,为了充分利用空间,我们实际上可以将删除的元素直接存储在二叉堆的最后一个元素中。例如:
删除堆顶,并将删除的元素作为最后一个元素。
继续删除,将删除的元素放到最后第二个位置
继续删除,将删除的元素放在最后第三个位置
等等…。
这样,对于一个包含n个元素的二叉堆,经过n-1次(不需要删除n次)删除后,数组就变成了有序数组。
那么,给你一个无序数组,我们需要将这个数组构造成一个二叉堆,然后通过将堆顶一一删除来实现堆排序。
事实上,它并没有被删除。相当于将堆顶的元素与堆尾交换,然后通过下沉将二叉树恢复为二叉堆。
代码如下:
public class HeapSort { /** * 下沉操作,执行删除操作相当于将最后一个* * 元素赋值给根元素,然后对根元素执行下沉操作* @param arr * @paramparent 到的元素下沉下标* @param length array length*/public static int[] downAdjust(int[] arr, intparent, int length) { //暂时保证下沉元素int temp=arr[parent]; //定位左子节点位置int child=2 * Parent + 1; //开始下沉while (child length) { //如果右子节点小于左子节点,则定位右子节点if (child + 1 length arr[child] arr [child + 1]) { child++; } //如果父节点小于等于子节点,则下沉结束if (temp=arr[child]) break; //单向赋值arr[parent]=arr[child ];父=子;子级=2 * 父级+ 1; } arr[父]=临时;返回arr; } //堆排序public static int[] heapSort(int[] arr, int length) { //构建2个分叉堆for (int i=(length - 2)/2; i=0; i--) { arr=downAdjust(arr, i, 长度); } //进行堆排序for (int i=length - 1; i=1; i--) { //将堆顶元素与最后一个元素交换int temp=arr[i]; arr[i]=arr[0]; arr[0]=温度; //接收器调整arr=downAdjust(arr, 0, i);返回arr; } //测试public static void main(String[] args) { int[] arr=new int[]{1, 3, 5,2, 0 ,10,6}; System.out.println(Arrays.toString(arr)); arr=heapSort(arr, arr.length); System.out.println(Arrays.toString(arr)); }}对于堆我直接给出了时间复杂度。有兴趣的可以自己推理一下。这并不难。堆的时间复杂度是O(nlogn)。空间复杂度为O(1)。
这里你可能会问,堆排序的时间复杂度是O(nlogn),和快速排序一样,归并排序的时间复杂度也是O(nlogn),那么使用时应该如何选择呢?
这里解释一下:快速排序的平均复杂度是O(logn)。事实上,快速排序最坏的时间复杂度是O(n^2.),而归并排序和堆排序都稳定在O(nlogn)。
我给你一个问题,比如我给你一个有n个元素的无序数组,让你找出第k大的数。那么你会选择哪种排序呢?
显然在这个问题中,堆排序是最好的。我们不需要对整个数组进行排序,我们只需要对前k 个数字进行排序。至于代码怎么实现,我就不给你们代码了。你可以尝试一下。
标题:什么是堆排序?有哪些典型应用?
链接:https://www.gbbxw.com/news/rj/20133.html
版权:文章转载自网络,如有侵权,请联系删除!
用户评论
堆排序在游戏开发中有什么神奇之处,你知道吗?
有7位网友表示赞同!
游戏中的性能优化大师们是不是常常提及堆排序?
有18位网友表示赞同!
如果你希望游戏运行流畅不受卡顿,堆排序技术不容忽视。
有12位网友表示赞同!
当游戏开发者说到算法性能时,堆排序总能成为热门话题之一。
有10位网友表示赞同!
"堆排序"这个概念让我对游戏背后的系统原理产生了极大兴趣。
有17位网友表示赞同!
在大型游戏中应用堆排序,可以显著减少加载时间,提升用户体验。
有19位网友表示赞同!
原来堆排序不仅用于数据处理,还能在游戏中优化玩家互动效率。
有8位网友表示赞同!
"堆排序”这个名字听起来挺枯燥的,但其实际应用在游戏界可大有学问!
有16位网友表示赞同!
深入理解了堆排序后,我对游戏的底层逻辑有了更深刻的认识。
有7位网友表示赞同!
想不到,在电子游戏中,算法还能起到提升流畅度和效率的作用。
有5位网友表示赞同!
通过游戏学习到的“堆排序”竟然与性能优化息息相关,真是妙哉!
有10位网友表示赞同!
"堆排序"的应用让人对游戏开发过程中的技术细节感到着迷不已。
有11位网友表示赞同!
原来每一个高性能操作背后都凝聚了像堆排序这样的复杂理论知识。
有8位网友表示赞同!
在电子竞技领域内,“堆排序”是如何帮助提高团队协作并赢得更多的比赛?
有20位网友表示赞同!
"了解堆排序后,我终于能理解为什么有的游戏运行更流畅、体验感更好了!"
有12位网友表示赞同!
“堆排序”的原理和实践对于新手玩家来说是个不小的挑战,但一旦掌握就能解锁新技能。
有18位网友表示赞同!
通过学习游戏内的数据优化方法,“堆排序”成为了提升游戏性能的关键一环。
有14位网友表示赞同!
游戏开发者用“堆排序”解决了大量的技术问题,可见这在游戏行业中的地位不容小觑。
有15位网友表示赞同!
"堆排序”的应用让我不禁感叹科技魅力与创意碰撞的火花如何激发无限可能。
有9位网友表示赞同!
对游戏设计有兴趣的人士可以通过学习“堆排序”,探索更多系统优化的新天地。
有9位网友表示赞同!