堆排序(排升序为啥建大堆,排降序为啥建小堆)

堆排序详解 上文提到的leetcode第215题除了快速排序的二分partition解法,还可以用堆排序来解决,小小一道medium题居然汇集了快排和堆排这两位卧龙凤雏,实属难得。 文章目录数据结构-堆完全二叉树堆堆排序思想构造大根堆代码 数据结构-堆 完全二叉树 首先,堆是一棵完全二叉树,因此其具备完全二叉树的全部特点: 除了最后一层外,其余层的节点数都达到最大值,而最后一层的节点都集中在左边。 节点的编号与其对应的满二叉树中节点编号相同 若最后一个非叶子节点的编号为i,则编号0~i的节点都是非叶子节点,编号i+1 阅读详情
AI摘要

本文深入解析堆排序的原理,包括完全二叉树的概念、顺序存储方式及如何通过建堆和向下调整完成排序过程。详细阐述了为何升序排序需建大堆,降序则需建小堆,并通过实例说明堆排序的步骤。

简介:

  之前对堆排序认识的不是很透彻,今天回过头来再把堆排序的知识整理整理!以及排升序为什么要建大堆,排降序要建小堆。

正文:

  首先我们要知道:
  ①堆的逻辑是一颗完全二叉树;
  ②它使用的是顺序存储(也就是数组);
  ③它的作用:一般都是用于找最值。

排序也就是对数组的元素按照大小规则进行摆放。

堆排序的过程:
1、建堆
2、对建好的堆进行向下调整。

可能有人会疑问?堆已经建立好了,为什么还要向下调整?
来看看下面的解释:
我们先给定一个数组arr[ ] = { 7, 6, 3, 5, 4, 1, 2 }; 将其排成一个大堆。如下图:
在这里插入图片描述
  当我们建好堆之后,我们发现这个堆层序遍历下来是一个降序的。那么要将它变成一个升序的顺序,就要将它逆序。
  也就是交换堆顶和最后一个元素的位置,然后从堆顶开始向下调整,每交换一个位置,就多一个数据已经排好升序。
  可能看到这还很迷糊。没关系,继续看下面的图。

在这里插入图片描述
我们可以看到,排升序的话,使用大堆是非常方便的,我们每次向下调整都可以得到剩余数据的最大值,即堆顶元素。然后放到最后,使用分治的思想,每调整一次,要排序的数据就少一个。当交换到最后一个结点时,数组已经排好序了。
因为是从堆顶选择第一个元素与最后一个元素交换,所以堆排序实质上还是选择排序。

那么有人会疑惑为什么不使用小堆排升序呢?
我们再想想:首先使用堆排序主要是用堆顶元素,如果使用小堆排升序,此时堆顶的元素是最小的,当我们取出堆顶元素时,此时小根堆的性质就变了,那么下次就找不到第二小的元素了,还要重新建堆。所以不能使用小堆排升序。有兴趣的可以自己来画图走一走。


堆排序的代码如下:

void Swap(int *a, int *b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
//建大堆
void AdjustDown(int arr[], int size, int root){
    int left = 2 * root + 1;
    int right = 2 * root + 2;
    int max;
    //没有左孩子
    if (left >= size){
         return;
    }
    //右孩子存在且大于左孩子
    if (right < size && arr[right] > arr[left]){
         max = right;
    }
    else{
         max = left;
    }
    if (arr[root] >= arr[max]){
         return;
    }
    Swap(arr + root, arr + max);
    AdjustDown(arr, size, max);
}
void CreateHeap(int arr[], int size){
    for (int i = (size - 1 - 1) / 2; i >= 0; i--){
         AdjustDown(arr, size, i);
    }
}
void HeapSort(int arr[], int size){
    CreateHeap(arr, size);
    for (int i = 0; i < size; i++){
         Swap(arr, arr + size - i - 1);
         AdjustDown(arr, size - i - 1, 0);
    }
}
PEMFC电化学入门:从电流密度到Tafel公式的实战计算指南 本文详细介绍了PEMFC电化学的基础知识,从电流密度计算到Tafel公式的应用,提供了实战计算指南。通过代码示例和常见问题排查,帮助工程师快速掌握燃料电池性能优化的关键参数,如交换电流密度和活化损失计算,适用于汽车动力和分布式发电等领域。 阅读详情

相关推荐

从零构建锂电池主动均衡系统:Simulink仿真中的Buck-Boost拓扑实战指南

本文详细介绍了如何在Simulink中从零构建基于Buck-Boost拓扑的锂电池主动均衡系统。通过仿真环境搭建、参数优化、控制策略设计和性能评估,为工程师提供了完整的实战指南,帮助快速验证和优化均衡算法,提升电池组一致性与寿命。

gitlab7runner的博客 896

谈谈堆排序,大顶堆,小顶堆

目录 1、前言 2、使用堆的原因 3、堆的特点 4、堆和普通树的区别 5、堆排序的过程 6、堆排序的代码实现 来源:jianshu.com/p/15a29c0ace73 1、前言 堆是一种非线性结构,可以把堆看作一个数组,也可以被看作一个完全二叉树,通俗来讲堆其实就是利用完全二叉树的结构来维护的一维数组但堆并不一定是完全二叉树 按照堆的特点可以把堆分为...

包磊磊的博客 3814

Windows下用RKDevTool解包update.img的完整流程(含常见错误排查)

本文详细介绍了在Windows系统下使用RKDevTool工具解包update.img固件的完整流程。从工具准备、环境搭建到逐步解包操作,重点解析了输出文件结构,并提供了修改分区后重新打包的实战方法。文章还针对解包失败、打包错误等常见问题提供了详细的排查与解决方案,旨在帮助嵌入式开发者和爱好者高效完成固件分析与定制工作。

aa123的博客 715

堆与堆排序

堆可以被看做一个一维数组,也可以被看作是棵完全二叉树。堆其实就是利用完全二叉树的结构来维护的一维数组。 堆主要用来做优先队列,因为它可以访问到最重要的元素,而在堆中搜索元素会比较慢。 升序排序用大顶堆,降序排序用小顶堆。以大顶堆为例,没做一次堆排序,就可以得到序列中的最大值,把它放到堆数组的最后面,则堆的末尾就是最大值了,则可以进行升序排序。

kk的任意门 1641

实战分享:如何用Jetson Nano+HM30图传搭建低空YOLOv5检测系统(附VNC避坑指南)

本文详细介绍了如何利用Jetson Nano和HM30图传搭建低空YOLOv5检测系统,重点解决了无人机应用中的硬件连接和VNC延迟优化问题。通过对比WiFi直连与图传方案的优劣,提供了网络配置、VNC优化及YOLOv5模型加速的实战技巧,帮助开发者实现高效稳定的低空目标检测系统。

weixin_29174385的博客 110

Python实现商品价格监控与波动分析爬虫项目

本文通过完整的代码示例和详细的技术讲解,展示了如何实现商品价格的自动监控和波动分析。该项目不仅适用于个人购物助手,还可以扩展为商家的竞品监控工具。通过结合数据抓取、存储、分析与可视化,能够帮助我们更好地理解市场趋势并做出优化决策。

2201_76125261的博客 1742

大顶堆和小顶堆和堆排序!!!!!!!!!!!!!!

一、大顶堆 二、小顶堆 三、堆排序 首先我讲一下大顶堆和小顶堆的基本概念大家先理解一下 所谓大顶堆通俗意义上来讲就是大的数放顶上,小的数放下面、也就是降序。所以需要保证每一个父节点都大于他的两个子节点。 小顶堆那肯定就是和大顶堆相反了,小的数放上面,大的数放下面,也就是升序、所以需要保证每一个父节点都小于他的两个子节点。 为了方便大家理解,我下面放上两个图。不然太抽象了。 当我们进行堆排序的时...

DeathRS的博客 2537

机器学习实战4-教育领域:学生成绩的可视化分析与成绩预测-详细分析

大家好,我是微学AI,今天给大家带来机器学习实战4-学生成绩的可视化分析与成绩预测,机器学习在教育中的应用具有很大的潜力,特别是在学生成绩的可视化分析与成绩预测方面。机器学习可以通过对学生的父母教育情况和学校表现等数据进行分析和挖掘,从而揭示潜在的学习模式和趋势。

微学AI的博客 7676

堆排序算法知识点总结

1. 在用堆排序算法排序时,如果要进行增序排序,则需要采用“大根堆”,减序排列则要采用“小根堆”。堆排序的方法:首先,将当前的数组调整为堆,也就是建立堆。然后把根与最后的元素交换,重新调整堆,然后再把调整后的根与倒数第二个元素交换,再重新调整堆,直到全部元素交换完毕。这样,对于大根堆,最大元素排列到了最后,是递增排序。而小根堆,最小元素排列到了最后,是递减排序。2. 找出若干个数中最大/最小的前K个

在努力! 4874

(一)激光线扫描-三维成像原理

激光线扫描是一种使用激光作为光源,通过特定的扫描设备(如光学镜头、电机驱动的镜头或电子扫描设备)将激光束引导到目标表面,并按照预定的路径进行扫描的技术。这种技术通常用于测量、检测、打印、切割等多种应用中。

FlyWine的博客 3629

matlab 显示曲面网格【2025最新版】

matlab点云工具箱对点云三维重建结果显示的函数。博客长期更新,本文最近更新时间为:2025年9月14日。

点云侠的博客 2580

二叉树---堆排序以及时空复杂度详解

向下调整建堆,节点越多调整次数越少,节点越少调整次数越多。 向上调整建堆,节点越多调整次数越多,节点越少调整次数越少。

Joker10085的博客 708

地统计插值学习心得(一)

(创建地统计图层工具用于根据现有的地统计图层或者地统计模型来创建包含新要素数据集的地统计图层,也就是使用构建好的地统计模型用到新的数据集中)这表明,远离极值的区域预测不受极值的影响,并且还表明,包括极值会导致钼元素浓度高的区域周围的预测明显变高。通常,我们使用同一个数据集进行建模和预测,但是在实际插值过程中,这两步的数据可以是不同的,这就是处理极值的诀窍。如果你的数据集有无法忽略的极值时(比如这些钼元素浓度),一种常见的方法是首先显式移除极值进行建模,然后在预测中使用整个数据集(包括极值)。

JData_Engineer的博客 286

堆排序(含证明)

对比之下,向下调整法建堆的时间复杂度更低,所以我们更推荐用向下调整法建堆。

2403_82706967的博客 1058

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

堆排序,TopK问题|向上调整建堆|向下调整建堆(C)

前面建立随机数文件的时候mod了个1000000,在文件里随机添加几个超过一百万的数,看是否出现在程序结果里,如果把这些随机插进去的数都能找到,就代表程序是正确的。把最大的数据选出来以后,把堆顶的数据和最后一个数据交换,最大的数据排好了,在把这个最后的最大的数据不看做堆里的数据,这样,剩下的数据的相对关系没动,左子树还是大堆,右子树还是大堆,把剩下的数看作堆,向下调整选出次大的,代价是。不能使用大堆,否则最大的数进堆以后,就挡在这里,剩下的数就无法进堆。找到以后,在这个非叶子节点的子树里,进行向下调整。

ChoSeitaku的博客 1090

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

堆排序:向上调整建堆

向下调整,就是把栈顶元素与最后一个元素交换,这样最大的元素就到了数组末尾,最大的元素就已经排序完成,之后的调整把它排除在外就行。这里是主函数的代码。先把堆的堆顶元素和最后一个元素交换,用end做最后一个元素的下标,再向下调整。就是把新插入的节点和它的父节点比较,如果新节点的值比父节点的值大,就把父节点的值和新节点的值交换。如果建小堆,那么堆顶元素就是最小的值,所以最小的已经排好了,那么把剩下的值看作一个堆(如果不把已经最小的排除在外,那么永远也找不到第二小的元素),这时会出现问题,父子兄弟关系变混乱。

2401_84276209的博客 371

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Java版本的堆排序(原理及代码)

堆排序原理:  堆排序指的是将大堆(小堆)堆顶(即下标为0)元素与堆的最后一个元素(下标为size)交换,将其余的元素再次调整成大堆(小堆),再次将堆顶(即下标为0)元素与堆的最后一个(下标为size-1)元素交换,将其余的元素再次调整成大堆(小堆)…………重复上述步骤,直至size = 0 关于升序或者降序应该建立什么堆??? 若想排升序即最大值应该在最后面,根据堆排序原理,应该建大堆,这样将堆...

zhao_miao的博客 425

Topk问题与堆排序(Java数据结构)

接触完堆之后,也逐渐对堆了如指掌,最后再来讨论一下两个问题。有如下场景:1、全国有几千所大学,我如何能够快速找出排名前10的大学?2、我如何对这10所大学排好序?为了用堆解决问题,接下来我们就来一起学习Topk问题的解法与堆排序!

多敲代码防脱发的博客 890

数据结构之二叉树堆的应用

数据结构中堆的应用:堆排序和top-k的问题

lulu_gh_yu的博客 869

【C语言 数据结构】堆与二叉树(下)

这里主要介绍的是堆排序,二叉树的遍历,以及之前讲题时答应过的简单二叉树问题求解

2301_79789645的博客 3855

排序算法上——插入,希尔,选择,堆排序

在希尔排序开始时增量较大,分组较多,每组的记录数目少,n小,此时直接插入最好和最坏时间复杂度n2差距很小,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di-1作为距离排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快。2. 然而在排序的时候,时间消耗过于庞大,因为在挪动元素时,会把堆内的序列和关系打乱,因此应该建大堆,然后利用算法进行调整。1.希尔排序的核心在于对数组进行预排序,值得注意的是,预排序只是让数组相对有序,而非达到真正的有序状态。

2303_81060385的博客 1512

数据结构 【堆排序】

上面两篇文章中,我们可以了解到大堆的堆顶存放的是堆中最大的元素,小堆的堆顶存放的是堆中最小的元素。利用堆的这个属性就可以实现排序的目的。如果排升序,那么使用大堆选取堆中最大的数据放置在堆顶,将堆顶元素与堆中最后一个元素进行交换,将最大的元素排除在外进行向下调整,循环遍历整个堆就可以得到原数据的升序排列。如果排降序,同样的道理,先选取小堆的堆顶,得到堆中最小的元素,将其与堆中最后一个元素进行交换位置,将最后一个元素排除在外,再进行向下调整,遍历整个堆,就会得到原数据的升序排列。

qq_70199082的博客 1231

堆的应用(建堆、堆排序、TOP-K问题)

给定一个数组,在此基础上进行建大堆操作。

zl_dfq的博客 1132

选择排序:直接选择排序、堆排序

选择排序:直接选择排序、堆排序

2302_76314368的博客 1278

堆实现TopK问题以及二叉树的基础知识铺垫_top-k问题 堆积树的优缺点

先选出最大的和最后一个元素交换,再向下调整,再不把最后一个数看成是堆里面的,紧接着选出次大的,和最后一个元素交换,再向下调整,不把最后一个元素看作是堆里面的,依次循环直到只剩最后一个元素了,就可以认为是有序的了。那就是建小堆了,选出最小的数与最后一个元素交换,再向下调整,紧接着不把它看作是堆里面的,再选次小,交换,向下调整,不看做堆元素,反反复复直到只剩最后一个元素就可以是降序了。观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

2401_84297796的博客 1031

堆实现TopK问题以及二叉树的基础知识铺垫_top-k问题 堆积树的优缺点(3)

面对左右子树不是小堆的情况下,向下调整算法的优化实现思路:如果左右子树不是堆的情况,使用向下调整算法肯定没有规律了,但是可以换一个角度考虑,从最后一个父亲位置开始把它作为一个子树,对它进行向下调整后这个子树就是小堆了,紧接着找到第二个子树依次…向下调整,最后左子树与右子树之间整体一调整就是一个堆了,已经用序列号标记好,将这几个圈起来的看作是一个子树,对每一个子树向下调整,会得到一个小堆,整体一调整会成一个大堆。

2401_84297618的博客 899
上一篇: STL之list的模拟实现
下一篇: C/C++中的static关键字
coolnut12138
博客等级 码龄9年 51粉丝 75原创
评论 12
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值