排序——堆排序

本节继续复习排序算法。这次复习排序算法中的堆排序。 堆排序属于选择排序。

目录

什么是堆?

堆排序

堆排序的思想

堆排代码

向下调整算法

 堆排整体


什么是堆?

在复习堆排序之前, 首先我们需要回顾一下什么是堆 。

堆的本质其实是一个数组。 它的物理结构本质上是一个数组。 但是它的逻辑结构是一棵完全二叉树。我们在判断一个数组是否是一个堆的时候根据的就是它的逻辑结构。

那么怎么根据它的逻辑结构判断是否是一个堆。 

首先堆的逻辑结构的二叉树的每一个孩子节点都大于它的每一个父亲, 就是堆。 这种堆叫做小堆。 如果它的逻辑结构的每一个孩子节点都小于它的父亲节点。 它同样是个堆, 同时这种堆叫做大堆。 

如图数组就是一个小堆

将该小堆的逻辑结构画出来就是这样的:

我们可以看到,在这棵二叉树之中的每一个父亲节点都小于它的孩子节点。 那么他就是一个小堆。 

大堆就是它的每个父亲节点都大于它的每个孩子节点

如图:

堆排序

堆排序的思想

堆排序的思想利用了大堆或小堆的结构。

我们从上面的解析可以发现。 大堆中, 第一个元素一定是整个数组中最大的那个元素;小堆中,第一个元素一定是数组中最小的那个元素。

堆排的核心就是每一趟都将堆的第一个元素和堆的最后一个元素交换位置。 然后让这个堆的元素个数减一。 同时通过向下调整算法重新建堆。 循环往复。 不断选出最大或者最小的那个数据放到堆的最后。

不知道向下调整算法可以去回顾本节:堆——c语言实现堆结构-CSDN博客

现在我们来分析一下堆的排序过程。 

我们使用小堆进行堆排:

 

第一步,将第一个元素也就是堆顶的元素和最后一个元素交换:

然后堆的大小减一:

向下调整算法重新建堆: 

 堆的第一个元素再次和堆最后一个元素交换位置:

 堆的大小减一:

 然后向下调整算法重新建堆:

然后堆的第一个元素再和堆的最后一个元素交换位置, 然后堆的大小减一, 然后向下调整算法调堆。 循环,一直到堆只剩下一个元素位置。 排好后就是这样的:​​​​​​​ 现在已经有序,同时是降序。 这时我们使用的是小堆排的。其实这里就是用大小堆控制升序降序。 小堆排的就是降序, 大堆排的就是升序。 

堆排代码

向下调整算法

我们先再来实现一次向下调整算法:


//向下调整建大堆。
void AdjustDownSort(int* a, int sz, int parent)
{}

a是要建堆的数组, sz是数组的大小。 parent是建堆的堆顶节点 

 


//向下调整建大堆。
void AdjustDownSort(int* a, int sz, int parent)
{int child = parent * 2 + 1;//先假设左孩子小。 }

 我们先假设左孩子比较大(注意, 我这里要建的是大堆)。


//向下调整建大堆。
void AdjustDownSort(int* a, int sz, int parent)
{int child = parent * 2 + 1;//先假设左孩子小。 while (child < sz) //控制条件是孩子不能超出整个数据。 {child = 2 * parent + 1;}
}

然后使用child指针控制循环结束。 当child指针超出整个数组的时候就不用再向下调整了。 

 


//向下调整建大堆。
void AdjustDownSort(int* a, int sz, int parent)
{int child = parent * 2 + 1;//先假设左孩子小。 while (child < sz) //控制条件是孩子不能超出整个数据。 {if (child + 1 < sz && a[child] < a[child + 1])//让child指向大的那个孩子。说明建大堆, 排升序。 {child++;}child = 2 * parent + 1;}
}

 因为我们是假设的左孩子比较大, 所以进入循环之后我们要比较一下左右孩子。如果右孩子更大的话就假设错误, child指针需要加加。

 


//向下调整建大堆。
void AdjustDownSort(int* a, int sz, int parent)
{int child = parent * 2 + 1;//先假设左孩子小。 while (child < sz) //控制条件是孩子不能超出整个数据。 {if (child + 1 < sz && a[child] < a[child + 1])//让child指向大的那个孩子。说明建大堆, 排升序。 {child++;}//if (a[child] > a[parent]) {Swap(&a[child], &a[parent]);parent = child;//继续向下调整。 父亲便孩子, 孩子变成孩子的孩子。child = 2 * parent + 1;}else {break;//如果父亲比小的孩子还要大, 那么这个父亲就是一个堆。 就不需要再调整建堆了。}//}
}

 然后在每次循环中都比较一下父亲节点和两个孩子中更小的节点。 如果孩子比父亲还要大。 就交换孩子节点和父亲节点。

如果孩子节点比父亲节点要小。 那么就说明这个堆已经建好了。 就跳出循环。

 堆排整体

一、


//堆排序
void HeapSort(int* a, int sz) 
{}

 首先, 堆排的函数名以及传参。 除了快排传参基本都是传要排序的数组和数组的大小。

二、


//堆排序
void HeapSort(int* a, int sz) 
{int end = sz - 1;//先建堆, 向下调整建大堆for (int i = (end - 1) / 2; i >= 0; i--)//从最后一个节点的父亲开始向下调整。  一棵子树一棵子树的建成堆。最后整体成堆{AdjustDownSort(a, sz, i);//向下调整算法建大堆。}//while (end > 0) {Swap(&a[0], &a[end]);//让第n个数据和堆顶最大的那个数据交换, 就能让第end个数据是最大的那个数据。 AdjustDownSort(a, end, 0);//第n个数据和堆顶数据交换后,前end - 1个数据只有堆顶不符合堆, 堆顶左右子树都是堆, 这时满足//向下调整算法。 然后向下调整。 end--;}}

堆排的实现过程就是我们上面分析的过程。 首先需要一个堆。 所以先建堆。 

建完堆之后就交换堆顶和最后一个数据。 然后堆的大小减一调堆。循环往复。  

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/720624.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

游戏引擎用什么语言开发上层应用

现在主流的游戏引擎包括&#xff1a; 1、Unity3D&#xff0c;C#语言&#xff0c;优点在于支持几乎所有平台 丹麦创立的一家公司&#xff0c;现已被微软收购。在中国市场占有率最高&#xff0c;也是社群很强大&#xff0c;一般解决方案也能在网上找到&#xff0c;教程丰富。物理…

Golang pprof 分析程序的使用内存和执行时间

一、分析程序执行的内存情况 package mainimport ("os""runtime/pprof" )func main() {// ... 你的程序逻辑 ...// 将 HeapProfile 写入文件f, err : os.Create("heap.prof")if err ! nil {panic(err)}defer f.Close()pprof.WriteHeapProfile(f…

139.乐理基础-一四五八度为何用纯?

上一个内容&#xff1a;138.乐理基础-等音、等音程的意义-CSDN博客 上一个内容里练习的答案&#xff1a; 以乐理里写的知识&#xff0c;没办法完全解释透彻 一四五八度为何用纯&#xff1f;这个问题&#xff0c;要透彻的话要从各个文明怎么发现音高、发明音高、制定规则等&…

Vue3+element-plus复杂表单分组处理

一、为什么表单要分组处理&#xff1f; 方便表单字段的复用&#xff1a;例如&#xff0c;你的表单有十个字段会在很多的表单都会用到&#xff0c;那么表单则需要进行分组进行表单复用&#xff1b;实现不同角色的表单权限控制&#xff1a;例如一个表单有60个字段&#xff0c;角…

VisualStudio 2022的安装

1.IDE 推荐最新版VisualStudio2022&#xff0c;功能十分强大&#xff0c;社区版就够用了。下载地址 2.安装 工作负载选择桌面开发&#xff0c;Web开发可以暂时不选中&#xff08;大部分都用不到&#xff09;。 单个组件选中NET 6.0和NET Frameword4.6.1 也就可以了。 后面安…

14-RPC-自研微服务框架

RPC RPC 框架是分布式领域核心组件&#xff0c;也是微服务的基础。 RPC &#xff08;Remote Procedure Call&#xff09;全称是远程过程调用&#xff0c;相对于本地方法调用&#xff0c;在同一内存空间可以直接通过方法栈实现调用&#xff0c;远程调用则跨了不同的服务终端&a…

汽车零部件制造中的信息抽取技术:提升效率与质量的关键

一、引言 在汽车制造业中&#xff0c;零部件的生产是整个制造流程的关键一环。这些零部件&#xff0c;包括但不限于制动系统、转向系统和传动系统&#xff0c;是确保汽车安全、可靠运行的基础。为了满足现代汽车工业对效率和质量的严格要求&#xff0c;制造商们纷纷投入到高度…

Jetpack Compose: Hello Android

Jetpack Compose 是一个现代化的工具包&#xff0c;用于使用声明式方法构建原生 Android UI。在本博文中&#xff0c;我们将深入了解一个基本的 “Hello Android” 示例&#xff0c;以帮助您开始使用 Jetpack Compose。我们将探讨所提供代码片段中使用的函数和注解。 入门 在…

软件测试--性能测试工具JMeter

软件测试--性能测试工具JMeter 主流性能测试工具1.主流性能测试工具Loadrunner和Jmeter对比 —— 相同点2.主流性能测试工具Loadrunner和Jmeter对比 —— 不同点JMeter基本使用JMeter环境搭建1.安装JDK:2.安装Jmeter:3.注意点:JMeter功能概要1. JMeter文件目录介绍1.1 bin目…

瑞_23种设计模式_享元模式

文章目录 1 享元模式&#xff08;Flyweight Pattern&#xff09;1.1 介绍1.2 概述1.3 享元模式的结构1.4 享元模式的优缺点1.5 享元模式的使用场景 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代码实现 4 JDK源码解析&#xff08;Integer类&#xff09; &#x1f64a; …

13-Java代理模式 ( Proxy Pattern )

Java代理模式 摘要实现范例 代理模式&#xff08;Proxy Pattern&#xff09;使用一个类代表另一个类的功能 代理模式创建具有现有对象的对象&#xff0c;以便向外界提供功能接口 代理模式属于结构型模式 摘要 1. 意图 为其他对象提供一种代理以控制对这个对象的访问2. 主…

力扣206反转链表

206.反转链表 力扣题目链接(opens new window) 题意&#xff1a;反转一个单链表。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 1&#xff0c;双指针 2&#xff0c;递归。递归参考双指针更容易写&#xff0c; 为什么不用头插…

3.1_2024ctf青少年比赛部分web题

php后门 根据x-powered-by知道php的版本 该版本存在漏洞&#xff1a; PHP 8.1.0-dev 开发版本后门 根据报错信息&#xff0c;进行提示&#xff0c;前 GET / HTTP/1.1 Host: challenge.qsnctf.com:31639 User-Agentt:12345678system(cat /flag);var_dump(2*3);zerodium12345678…

【小白学机器学习6】真实值,观测值,拟合值,以及数据的误差的评价:集中趋势,离散度,形状等

目录 1 世界上有哪几种值&#xff1f;只有3种值 1.1 真值/真实值/理想值/主观值&#xff08;形而上学世界里&#xff09; 1.2 实际值/现实值/观测值/样本值&#xff08;看到的/记录下来的&#xff09; 1.3 拟合值/预测值&#xff08;算出来的&#xff09; 2 对数据的各种…

springboot项目单纯使用nacos注册中心功能

Spring Boot 项目完全可以单独使用 Nacos 作为注册中心。Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。它支持服务的注册与发现&#xff0c;能够与 Spring Boot 应用无缝集成&#xff0c;为微服务架构提供了强大的支持。 在使用 Nacos 作为注册中…

Python实现DMI工具判断信号:股票技术分析的工具系列(3)

Python实现DMI工具判断信号&#xff1a;股票技术分析的工具系列&#xff08;3&#xff09; 介绍算法解释 代码rolling函数介绍完整代码 介绍 先看看官方介绍&#xff1a; DMI (趋向指标&#xff09; 用法 1.PDI线从下向上突破MDI线&#xff0c;显示有新多头进场&#xff0c;为…

BUUCTF---[BJDCTF2020]藏藏藏1

1.题目描述 2.下载附件&#xff0c;解压之后是一张图片和一个文本 3.把图片放在winhex,发现图片里面包含压缩包 4.在kali中使用binwalk查看&#xff0c;然后使用foremost分离&#xff0c;在使用tree查看分离出来的文件&#xff0c;最后将zip文件使用unzip进行解压。步骤如下 5.…

pdf编辑软件哪个好用?5款PDF编辑器分享

pdf编辑软件哪个好用&#xff1f;PDF编辑软件在现代办公和学术研究中发挥着举足轻重的作用&#xff0c;它们不仅具备基础的编辑和修改功能&#xff0c;还能够支持多种注释工具&#xff0c;帮助我们高效地管理和整理PDF文件。无论是需要调整文档布局、添加文本或图像&#xff0c…

C++ 前缀和

目录 例1 例2 例3 例4 例5 例6 例7 例8 例1 DP34 【模板】前缀和 分析&#xff1a;dp和arr的大小并不是固定的&#xff0c;就是有没有偏移量&#xff0c;这里的n是从1开始&#xff0c;不如直接放到下标1处&#xff0c;在最后的减法时&#xff0c;如果用第一个参考代码会…

rtt的io设备框架面向对象学习-touch设备

目录 1.触摸设备基类2.触摸设备基类的子类3.初始化/构造流程3.1设备驱动层3.2 设备驱动框架层3.3 io设备管理层 4.总结5.使用5.1实例 1.触摸设备基类 此层处于设备驱动框架层。此层的类是抽象类。 在/ components / drivers / include / drivers /touch.h定义了如下touch设备…