八大排序算法——堆排序

堆排序算法(图解详细流程) 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录堆排序基本介绍大顶堆举例说明小顶堆举例说明堆排序的基本思想堆排序步骤图解说明堆排序的基本思路总结 堆排序基本介绍 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏最好,平均时间复杂度均为O(nlogn),他也是不稳定排序 堆是具有以下性质的完全二叉树,每个节点的值都大于或等于其左右孩子节点的值,称为大顶堆,注意:没有要求节点的左孩子的值和右孩子的值的大小关系。 每个结点的值都小于或等于其左 阅读详情
AI摘要

本文详细介绍了堆排序算法的工作原理,包括如何构建大根堆并利用其特性进行排序。通过具体的实例展示了堆排序的具体步骤,并提供了完整的C语言实现代码。

八大排序

排序,分为内部排序和外部排序,内部排序是指将数据记录在内存中进行排序,而外部排序因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存,所以称之为外部排序,我们这里讲的八大排序全部属于内部排序。

这里写图片描述

八大排序时间/空间复杂度及稳定性

这里写图片描述

堆排序

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。这里要注意的是堆排序采用的是完全二叉树的思想,但它的存储结构采用的是数组。

堆排序的过程(大根堆)
  • 调整堆:调整堆即是将最初无规则的堆调整为大根堆。它的每一次调整都是将非叶子结点i与其左孩子left[i]和右孩子light[i]进行比较,若非叶子结点i不是其中最大的,那么将其与最大的结点位置互换。堆的第一次调整是从最后一个非叶子结点开始依次向根节点调整的,这就是为什么它要采用完全二叉树的原因,因为这样可以快速的在数组中定位最后一个非叶子结点,即a[n/2-1],其中a是待排序的数组,n是数组a的下标值。那么就是说,下标为n/2-1的结点就是最后一个非叶子节点。堆的第一次调整函数的调用关系大概可以总结为循环调用+递归调用。其过程如下:
    • 初始完全二叉树
      初始完全二叉树
    • 数值3为最后一个非叶子结点,将其与它的孩子结点相比较,8>3,位置互换
      这里写图片描述
    • 判断被调整后的结点3是否为非叶子结点,3不是,函数调用进入下一层循环,将结点7与它的左右儿子结点相比较,20>17>7,将结点20与结点7位置互换
      这里写图片描述
    • 判断被调整后的结点7是否为非叶子结点,7不是,函数调用进入最后一层循环,将结点16与它的左右儿子结点相比较,20>16>7,将结点16与结点20位置互换
      这里写图片描述
    • 判断被调整后的结点16是否为非叶子结点,16是,函数进行递归调用,将结点16与它的左右儿子结点相比较,17>16>7,将结点17与结点16位置互换
      这里写图片描述
    • 判断被调整后的结点16是否为非叶子结点,16不是,循环结束,堆调整完毕。
  • 堆排序:可以看到,上面的调整堆算法循环调用执行完毕以后,结果是一个大根堆,堆排序所要做的就是将堆顶元素20与最后一个元素3互换位置,即将a[0]与a[n-1]互换位置,换位置之后a[0]至a[n-2]元素又组成一个新的堆,这时的调整堆与第一次调整刚好相反,它是从堆顶元素开始调整,一直往下延伸,是一个纯递归的过程,具体过程如下:
    这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述
    到这里,排序就算是执行完了,从上述过程可知,堆排序其实也是一种选择排序,是一种树形选择排序。只不过直接选择排序中,为了从a[1…n]中选择最大记录,需比较n-1次,然后从a[1…n-2]中选择最大记录需比较n-2次。事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的特点保存了部分前面的比较结果,因此可以减少比较次数,这就是为什么第一次调整堆是从下往上,而之后都是从上往下。对于n个关键字序列,最坏情况下每个节点需比较log2(n)次,因此其最坏情况下时间复杂度为nlogn。堆排序为不稳定排序,不适合记录较少的排序。下面是堆排序的c语言实现:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>

//堆调整算法
void HeapAdjust(int num[],int i,int length)
{
    //定义max保存以num[i]为根的最小堆中最大值的下标,初始值为i
    int max=i;
    //判断num[i]是否为根结点 (下标i<=length/2-1的结点都是根节点)
    if(i<=length/2-1)
    {
        //判断num[2*i+1]是否在堆内,若在,判断其是否大于num[max],若大于,将其下标2*i+1赋予给max
        if((2*i+1)<length && num[2*i+1]>num[max])
        {
            max=2*i+1;
        }
        //判断num[2*(i+1)]是否在堆内,若在,判断其是否大于num[max],若大于,将其下标2*(i+1)赋予给max
        if((2*(i+1))<length && num[2*(i+1)]>num[max])
        {
            max=2*(i+1);
        }
        //若i不等于max,则说明以num[i]为根的最小堆中num[max]是最大值,将num[max]与根结点num[i]交换位置
        if(i!=max)
        {
            num[i]=num[i]^num[max];
            num[max]=num[i]^num[max];
            num[i]=num[i]^num[max];
            //交换后,为防止以num[max]为根结点的最小堆结构发生变换,再次调用堆调整算法
            HeapAdjust(num,max,length);
        }
    }
}
//堆排序算法
void HeapSort(int num[],int length)
{
    int i;
    //找到最后一个非叶子结点,先从最后一个非叶子结点组成的最小堆进行堆调整
    for(i=length/2-1;i>=0;i--)
        //调用调整堆算法将数组从下往上调整为大根堆
        HeapAdjust(num,i,length);
    for(i=length-1;i>0;i--)
    {
        //将数组第一个数和最后一个数换位置
        num[i]=num[i]^num[0];
        num[0]=num[i]^num[0];
        num[i]=num[i]^num[0];
        //继续调用调整堆算法,将剩余数据组成的堆从上往下调整为大根堆
        HeapAdjust(num,0,i);
    }
}
int main()
{
    int i;
    int num[]={8,5,7,12,48,36,4};
    HeapSort(num,sizeof(num)/sizeof(int));
    for(i=0;i<sizeof(num)/sizeof(int);i++)
    {
        printf("%d\t",num[i]);
    }
    printf("\n");
}

堆排序的基本概念和基本思路 一 堆排序基本介绍 1 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序, 它的最坏、最好、平均时间复杂度均为 O(nlogn), 它也是不稳定排序。 2 堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,这种情况称为大顶堆,注意:没有要求结点的左孩子的值和右孩子的值的大小关系。 3 每个结点的值都小于或等于其左右孩子结点的值,这种情况称为小顶堆。 4 大顶堆举例说明 5 小顶堆举例说明 6 一般升序采用大顶堆, 降序采用小顶堆。 二 堆.. 阅读详情

相关推荐

堆排序详细图解(通俗易懂)

什么是堆 堆是一种叫做完全二叉树的数据结构,可以分为大根堆,小根堆,而堆排序就是基于这种结构而产生的一种程序算法。 堆的分类 大根堆:每个节点的值都大于或者等于他的左右孩子节点的值 小根堆:每个结点的值都小于或等于其左孩子和右孩子结点的值 两种结构映射到数组为: 大根堆: 小根堆: //父-->子:i--->左孩子:2*i+1, 右孩子:2*i+2; //子-->父:i--->(i-1)*2;(i为下标元素) 排序思想 1.首先将待排序的数...

oorik的博客 32万+

十大经典排序算法----堆排序(超详细)

堆排序,超详细,C语言版

m0_73096566的博客 2万+

基于 AUTOSAR 的域控产品软件开发进阶探索

本文深入探讨了AUTOSAR架构在汽车域控产品开发中的进阶应用。首先从系统设计角度分析了AUTOSAR分层架构原理及其在域控产品中的优化部署策略;其次详细介绍了Davinci和EBTresos等主流工具链的特点与协同使用方法;然后重点阐述了ASPICE流程与功能安全/信息安全标准的实施要点;最后分享了多核车载芯片(如NXP S32G)的适配经验与优化实践。通过架构设计、工具运用、标准遵循和芯片适配四个维度的专业解析,为域控产品的AUTOSAR开发提供了系统性指导。

SiArch的博客 1199

堆排序详解(Heap Sort)

构造的过程就是将无序的序列构造成一个堆的过程。堆的定义是:对于任意一个非叶子节点 i,其左子节点为 2i+1,右子节点为 2i+2,且父节点的值大于等于(或小于等于)其子节点的值。因此,我们可以从最后一个非叶子节点开始,依次将其与其子节点比较,如果不满足堆的定义,则交换位置,直到整个序列构造成一个堆为止。排序的过程就是将堆顶元素与最后一个元素交换位置,然后将剩余元素重新构造成一个堆的过程。每次交换后,堆的大小减一,因此我们可以通过一个变量来记录堆的大小,从而将排序的过程限制在堆的范围内。

Wzill 5665

Oracle Scheduler任务故障诊断 实战指南

当基础环境无异常时,需聚焦任务本身的配置与状态。定义(JOB)→ 调度(SCHEDULE)→ 执行(SLAVE进程)→ 日志(LOG),每个环节都可能存在卡点。Oracle Scheduler任务的“隐性故障”看似棘手,实则是环境配置、资源竞争、时间逻辑等问题的集中体现。通过本文的诊断工具和排查思路,你可以构建从“基础环境→任务配置→执行链路→日志追踪”的全维度分析体系,让每一个“消失”的任务都无所遁形。

Nuzbb的博客 1074

STM32开发实战--解决STM32CubeMX生成代码时钟初始化卡死问题

本文详细分析了STM32CubeMX生成代码在时钟初始化阶段卡死的问题,提供了多种解决方案,包括简单修改和稳健的等待机制。通过深入探讨HAL库的时钟初始化陷阱及硬件层面的根本原因,帮助开发者快速定位并解决STM32开发中的常见问题。

weixin_26965807的博客 441

八大排序算法---堆排序

这是一个大顶堆,每个父节点都比孩子大。 package suanfa; import java.util.Arrays; public class Duipaixu { //维护大顶堆 static void dadingdui(int[] arr,int n,int i) { int largest = i;//父节点i int lson = 2*i+1;//左孩子 int rson = 2*i+2;//右孩子 //如果哪个孩子的值大于父节点则把最大值的下标给到lar...

weixin_57711380的博客 758

Lora无线温湿度传感器方案

综上所述,Lora无线温湿度传感器以其长距离传输、低功耗、高稳定性、精准测量、无线传输以及广泛的应用场景等特点,在环境监测领域展现出了强大的竞争力和广泛的应用前景。Lora无线温湿度传感器广泛应用于各种需要远程监控和数据采集的场景,如仓储、农业、机房、楼宇、交通、工业、矿产、电力等领域。Lora无线温湿度传感器是一种采用Lora无线通信技术进行数据传输的温湿度监测设备。四、产品参数(以某款工业级Lora温湿度传感器为例)

weixin_46632654的博客 759

八大排序算法--堆排序

参考文章链接:https://www.cnblogs.com/skywang12345/p/3602162.html 原理: 指利用堆这种数据结构所设计的一种排序算法。 初始化堆:将数列a[1...n]构造成大(小)顶堆。 交换数据:将a[1]和a[n]交换,使a[n]是a[1...n]中的最大(小)值;然后将a[1...n-1]重新调整为大(小)顶堆。 接着,将a[1]和a[n-1]交换,使a[n-1]是a[1...n-1]中的最大(小)值;然后将a[1...n-2]重新调整为大(小)顶堆。 .

xyq_mxnx的博客 187

ZEMAX知识点:坐标间断面(coordinate break)

zemax知识点:坐标间断面

weixin_47638568的博客 1万+

实验四 基于IDEA+SpringBoot+Maven+Thymeleaf的系统实现实验目的

通过这次实验,我学习了如何成功进行IDEA+SpringBoot+maven的系统实现,搭建好IDEA+SpringBoot+maven的系统环境,成功地安装并配置了maven的运行环境,学会了创建springboot的三种方式,并且能将之前的实验结合起来运用。pom.xml中引入thymeleaf依赖,在classpath:/templates/下新建HTML页面(可采用实验一创建的页面),新建controller进行测试,访问页面后返回success成功数据。同时掌握和thymeleaf的基本语法。

m0_73502929的博客 1379

八大排序算法之堆排序

JAVA实现堆排序 堆排序 利用:顺序结构的二叉树 原理:借用大顶堆和小顶堆 堆的分类 1.大顶堆(大根堆):父节点的值大于任意一个子节点 2.小顶堆(小根堆):父节点的值小于任意一个子节点 步骤: 1.构造一个大顶堆,取堆顶数字(最大值) 2.剩下的数字再构造一个大顶堆,取堆顶数字(剩余数中的最大值) 3.重复以上操作,直到取完堆中的数字 图片示例: 代码: //堆排序 public static void heapSort(int[] arr) { /* 开始位置是最后一个元素的父节点

qq_42412309的博客 215

CloudCompare 二次开发(36)——非均匀体素降采样

使用CloudCompare与PCL编程实现的非均匀体素降采样。

点云侠的博客 746

C语言八大排序算法性能实测:10万数据下快排与堆排序耗时对比

本文通过实测对比C语言中八大经典排序算法在10万随机整数排序场景下的性能表现,重点分析快速排序与堆排序的耗时差异。测试结果显示,快速排序平均耗时仅0.016秒,表现最优;堆排序紧随其后,耗时0.022秒。文章详细解析了各排序算法的实现原理、时间复杂度及适用场景,为开发者提供了实用的排序算法选择指南。

csxc65837的博客 419

路径跟踪 | 图解纯追踪算法Pure Pursuit(附ROS C++/Python/Matlab仿真)

纯追踪算法(Pure Pursuit)参考了人类驾驶行为,其基本思想是在待跟踪路径上设置预瞄点(goal-ahead),通过简单的几何方法驱动机器人跟踪预瞄点直至抵达目标位置.本文详细推导纯追踪算法的理论原理及其变种——自适应纯追踪算法(APP)和规范化纯追踪算法(RPP),并提供ROS C++/Python/Matlab三种仿真实现加深理解

FRIGIDWINTER的博客 8409

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

八大排序算法 之 堆排序

例如数组 a={19,3,60,7,1,15,33,24,45,32,79,85};排序思想:1,堆排序也是选择排序的一种,根据堆得特性,每次把最大或最小值(本次以最大值为例)拿出来,按序排列;2,堆排序是对普通选择排序的一种优化:如果是一个稳定堆,每次在选择最大值时,只用沿着二叉树其中一个分叉去交换即可,其他分叉符合堆得特性(因是排好的稳定堆),可以看作是稳定的,不用重排交换,省去了绝大多数的比...

七月流星 488

数学建模模型总结

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

八大排序算法-堆排序

基本思想 堆排序是一种树形选择排序,是对直接选择排序的有效改进。 堆的定义如下:具有n个元素的序列(k1,k2,…,kn),当且仅当满足 时称之为堆。由堆的定义可以看出,堆顶元素(即第一个元素)必为最小项(小顶堆)。 若以一维数组存储一个堆,则堆对应一棵完全二叉树,且所有非叶结点的值均不大于(或不小于)其子女的值,根结点(堆顶元素)的值是最小(或最大)的。如: (a)大顶堆序列:

Hist_花透的博客 2483

Camera2Demo

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

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

(Java版)八大排序算法(希尔排序,快速排序,堆排序等)

/** * 分类 ------------ 内部比较排序 * 数据结构 --------- 数组 * 最差时间复杂度 ---- 每次选取的基准都是最大(或最小)的元素,导致每次只划分出了一个分区,需要进行n-1次划分才能结束递归,时间复杂度为O(n^2) * 最优时间复杂度 ---- 每次选取的基准都是中位数,这样每次都均匀的划分出两个分区,只需要logn次划分就能结束递归,时间复杂度为O(nlogn) * 平均时间复杂度 ---- O(nlogn) * 所需辅助空间 ------ 主要是递归.

Mrbugu的博客 642

八大排序算法 —— 堆排序

堆排序 堆的概念: 堆:本质是一种数组对象。特别重要的一点性质:任意的叶子节点小于(或大于)它所有的父节点。对此,又分为大顶堆和小顶堆,大顶堆要求节点的元素都要大于其孩子,小顶堆要求节点元素都小于其左右孩子,两者对左右孩子的大小关系不做任何要求。利用堆排序,就是基于大顶堆或者小顶堆的一种排序方法。下面,我们通过大顶堆来实现。 堆排序: 堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大...

C先生的博客 784

八大排序算法~堆排序

(2)for循环(从 i=最后一个结点位置开始直到i=第一个结点 结束):取根结点放于后座~即进行交换,根结点与后座最后一个位置进行交换,然后重构成新的大根堆,为什么不能for循环 调整成堆,然后取根结点,然再次调整成堆,然后再取根结点,再调整成堆。咱在对剩余的n-1个结点构建成一个新的大根堆,然后又取根结点放到后座上倒数第二个位置,然后对剩余的n-2个结点构建成一个新的大根堆,然后又取根结点放到后座上倒数第三个位置,再取根节点跟后座倒数第二个位置交换,然后重新构建新的大根堆,然后。

m0_66468899的博客 291

【八大排序算法之堆排序—Java】

堆排序 堆的结构可以分为大顶堆和小顶堆,是一个完全二叉树。 首先说明什么是完全二叉树: 若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。例如下图就不是一个完全二叉树,虽然1,2层均达到最大个数,但是第三层的节点应几种在左侧,即点7应该位于8的左子节点 其次说明什么是大顶堆和小顶堆: 每个结点的值都大于其左子节点和右子结点的值,称之为大顶堆;每个结点的值都小于其左子节点和右子结点的值,称之为小顶堆。下图即为大顶

weixin_47714239的博客 1132

八大排序算法详解——堆排序

基本思想 堆的定义n个关键字序列kl,k2,…,kn称为堆,当且仅当该序列满足如下性质之一(简称堆性质): ki≤k2i且ki≤k2i+1 或 ki≥k2i且ki≥k2i+1(1≤i≤FLOOR(n/2))若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若 存在)结点的关键字。 小根堆:

cy__dream的博客 848
上一篇: 稠密索引与稀疏索引
下一篇: 八大排序算法——冒泡排序
Jeaforea
博客等级 码龄10年 30粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值