【排序】5.堆排序(详细图解)

文章目录

  • 前言
  • 1.建堆方法的选择
  • 2.优先使用向下调整的原因
  • 3.堆排序图解(大堆-升序为例子)
    • 3.1 向下调整法-建大堆
    • 3.2 进行堆排序
  • 4.堆排序代码
    • 4.1 向下调整法
    • 4.1. 1 小堆
    • 4.1. 2 大堆
    • 4.2 堆排序
  • 5. 关于小堆——降序
  • 6.性能分析


前言

🐱个人主页: 代码探秘者
🐭C语言专栏:C语言
🐰C++专栏: C++ / STL使用以及模拟实现/C++11新特性
🐹数据结构专栏: 数据结构 / 十大排序算法
🐶 Linux专栏: Linux系统编程 / Linux网络编程(准备更新)
🌈喜欢的诗句:天行健,君子以自强不息.
pic_8da49713.png



在这里插入图片描述


在这里插入图片描述


1.建堆方法的选择

(1). 建堆
升序:建大堆
降序:建小堆

(2). 利用堆删除思想来进行排序
建堆和堆删除中都用到了向下调整因此掌握了向下调整,就可以完成堆排序。

2.优先使用向下调整的原因

对于最大堆,理论上可以采用向上调整的方法来构建,但实际上并不常用

  • 这是因为向上调整的方法在构建最大堆时效率较低,时间复杂度为O(nlogn),与直接插入法相同,而向下调整(堆化)的方法时间复杂度为O(n),更为高效。

为什么向上调整不常用:

效率问题:如前所述,向上调整建堆的时间复杂度为O(nlogn),而向下调整建堆的时间复杂度为O(n)。在构建堆时,我们通常希望尽可能高效,因此更倾向于使用向下调整的方法。

操作复杂性向上调整需要在每次插入新元素后,将新元素与其父节点比较并可能进行交换,直到它找到合适的位置。这个过程涉及到多次的比较和交换,操作相对复杂

堆的性质:在最大堆中,我们希望较大的值靠近根节点,而较小的值靠近叶子节点。向下调整的方法更自然地符合这一性质,因为它从最后一个非叶子节点开始,逐个向下调整直到根节点

3.堆排序图解(大堆-升序为例子)

3.1 向下调整法-建大堆

原始数据为a[] = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7},采用顺序存储方式,对应的完全二叉树如下图所示:
在这里插入图片描述

  • (1) 选最后一个非叶子结点

在这里插入图片描述

  • (2)逐个向下调整直到根节点
    在这里插入图片描述

3.2 进行堆排序

  • 建好大堆用我们刚刚上面的从最后一个非叶子结点,从下往上,一直到根结点,进行向下调整法
  • 根节点和最后一个结点交换(这样最大的不就放最后了嘛

在这里插入图片描述

  • 然后从根节点(堆顶)又继续向下调整
    在这里插入图片描述
    这样20是最大的,就排好在最后了

  • 之后交换5和17
    在这里插入图片描述

  • 然后向下调整这样排好17,交换3和16
    在这里插入图片描述

  • 交换好,然后向下调整,继续交换5和4,调整后

  • 交换4和3,然后调整
    在这里插入图片描述

  • 这样就完成了

在这里插入图片描述

4.堆排序代码

4.1 向下调整法

4.1. 1 小堆

我们通过从根结点开始的向下调整算法可以把它调整成一个小堆

  • 选出最小的孩子
  • 最小孩子比父亲小就交换上来
  • 更新parent和minchild,一直循环到最后
//向下调整:从哪里开始
//删除调用
void AdjustDown(DataType* a, int n, int parent)
{//先找到最小的孩子int minchild = 2 * parent + 1;	//假设左孩子最小while (minchild < n){//右孩子存在,而且小于左孩子if (minchild + 1 < n && a[minchild + 1] < a[minchild]){minchild++;		//更新最小为右孩子}//开始向下调整//小堆为例)if (a[minchild] < a[parent]){Swap(&a[minchild], &a[parent]);	//交换//更新parent和minchildparent = minchild;minchild = 2 * parent + 1;}else{break;}}
}

4.1. 2 大堆

  • 选出最大的孩子
  • 最大孩子比父亲大,就交换上来
  • 更新parent和minchild,一直循环到最后
//向下调整:							从哪里开始
//删除调用
void AdjustDown(DataType* a, int n, int parent)
{//先找到最大的孩子int maxchild = 2 * parent + 1;	//假设左孩子最小while (maxchild < n){//右孩子存在,而且大于左孩子if (maxchild + 1 < n && a[maxchild+ 1] > a[maxchild]){maxchild++;		//更新最大为右孩子}//开始向下调整//大堆为例if (a[maxchild] > a[parent]){Swap(&a[maxchild], &a[parent]);	//交换//更新parent和minchildparent = maxchild;maxchild = 2 * parent + 1;}else{break;}}
}

4.2 堆排序

//交换
void Swap(DataType* px, DataType* py)
{DataType tmp = *px;*px =*py;*py = tmp;
}void HeapSort(int* a, int n)
{//向上调整建堆 不推荐nlogn// 	for (int i = 1; i < n; i++)//{//	AdjustUp(a, i);//}//向下调整建堆 O(N)for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, n, i);		//调用向下调整法}//堆排序//开始:堆顶和最后一个元素交换int end = n - 1;				while (end > 0){//之后:堆顶和没有排好的最后一个元素交换Swap(&a[0], &a[end]);	//从根结点开始向下调整	AdjustDown(a, end, 0);		--end;		//排好一个}
}
void HeapSortTest()
{int a[] = { 50,100,70,65,60,32 };int n = sizeof(a) / sizeof(a[0]);HeapSort(a, n);for (int i = 0; i < n; i++){printf("%d ", a[i]);}
}

5. 关于小堆——降序

  • 把向下调整建大堆,该成建小堆

  • 其他步骤差不多

6.性能分析

时间复杂度O(n log n),其中n是数组的长度

空间复杂度O(1),堆排序是原地排序不需要额外的存储空间。

稳定性堆排序是不稳定的排序算法相同的元素可能在排序后改变相对顺序

适用性:由于堆排序是原地排序,适用于空间受限的情况。同时,它也适用于大数据量的排序

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

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

相关文章

头歌——机器学习(线性回归)

文章目录 线性回归简述答案 线性回归算法答案 线性回归实践 - 波斯顿房价预测LinearRegression代码 利用sklearn构建线性回归模型示例代码如下&#xff1a; 代码 线性回归简述 简单线性回归 在生活中&#xff0c;我们常常能碰到这么一种情况&#xff0c;一个变量会跟着另一个变…

技术美术百人计划 | 《5.4 水体渲染》笔记

一、水体渲染的波形模拟技术-基于物理 基于物理的波形模拟方法&#xff1a; 欧拉方法&#xff08;Eulerian approaches&#xff09;[Kass 1990]拉格朗日方法&#xff08;Lagrangian approaches&#xff09; [Stam 1995]欧拉-拉格朗日混合方法&#xff08;Hybrid approaches&a…

使用 Sortable.js 库 实现 Vue3 elementPlus 的 el-table 拖拽排序

文章目录 实现效果Sortable.js介绍下载依赖添加类名导入sortablejs初始化拖拽实例拖拽完成后的处理总结 在开发过程中&#xff0c;我们经常需要处理表格数据&#xff0c;并为用户提供便捷的排序方式。特别是在需要管理长列表、分类数据或动态内容时&#xff0c;拖拽排序功能显得…

Chrome与火狐的安全功能全面评估

在当今数字化时代&#xff0c;网络安全已成为用户最为关注的问题之一。作为两款广受欢迎的浏览器&#xff0c;Chrome和火狐&#xff08;Firefox&#xff09;都提供了多种安全功能来保护用户的在线隐私和数据安全。本文将全面评估这两款浏览器的安全功能&#xff0c;帮助用户更好…

Java-02

笔试算法&#xff1a; 41. 回文串 我们称一个字符串为回文串&#xff0c;当且仅当这个串从左往右和从右往左读是一样的。例如&#xff0c;aabbaa、a、abcba 是回文串&#xff0c;而 ab、ba、abc 不是回文串。注意单个字符也算是回文串。 现在&#xff0c;给你一个长度为n的…

Windows实用工具推荐(uTools+截图工具Snipaste)

闲言少叙,直奔主题 uTools 官网下载地址 uTools官网 - 新一代效率工具平台 这是工具的输入命令的样式,主题颜色可以自己设置,点击右边的头像进入主页 左侧是已经安装的工具,可以根据自己喜好安装各种实用小工具 可以自定义设置呼出菜单的快捷键 这款工具拥有很多功能,我推荐…

ViT面试知识点

文章目录 VITCLIPSAMYOLO系列问题 VIT 介绍一下Visual Transformer&#xff1f; 介绍一下自注意力机制&#xff1f; 介绍一下VIT的输出方式 介绍一下VIT做分割任务 VIT是将NLP的transformer迁移到cv领域&#xff0c;他的整个流程大概如下&#xff1a;将一张图片切成很多个pat…

STM32之串口字库更新

1.串口通讯介绍 串口通讯&#xff08;Serial Communications&#xff09;是一种通过串口进行数据传输的通讯方式&#xff0c;通过串行口每次传输一个字节的数据&#xff0c;按照约定的协议进行数据的传输和接收。串口通讯的原理是利用串行口的发送和接收线路&#xff0c;将需要…

【大语言模型】ACL2024论文-06 探索思维链COT在多模态隐喻检测中的应用

【大语言模型】ACL2024论文-06 探索思维链COT在多模态隐喻检测中的应用 目录 文章目录 【大语言模型】ACL2024论文-06 探索思维链COT在多模态隐喻检测中的应用目录摘要研究背景问题与挑战如何解决创新点算法模型1. 知识总结模块&#xff08;Knowledge Summarization Module&…

第三十一章 单页与多页应用程序概念

目录 一、概述 ​二、单页与多页对比 一、概述 单页面应用(SPA): 所有功能在一个HTML页面上实现&#xff0c;如网易云音乐。 https://music.163.com/ 多页应用&#xff1a;通过多个HTML页面组合实现整个应用网站的功能。 二、单页与多页对比 单页面应用的主要场景&#xff1…

开源 AI 智能名片 2 + 1 链动模式 S2B2C 商城小程序中积分使用价值的拓展策略

摘要&#xff1a;本文围绕开源 AI 智能名片 2 1 链动模式 S2B2C 商城小程序&#xff0c;深入探讨其积分使用价值的丰富策略。详细分析积分兑换礼品、会员升级、积分抵现等方式在该特定商城小程序环境下的应用特点、存在问题及对用户和商城的影响&#xff0c;旨在为商城的优化运…

C++ | Leetcode C++题解之第526题优美的排列

题目&#xff1a; 题解&#xff1a; class Solution { public:int countArrangement(int n) {vector<int> f(1 << n);f[0] 1;for (int mask 1; mask < (1 << n); mask) {int num __builtin_popcount(mask);for (int i 0; i < n; i) {if (mask &am…

【Linux 25】网络套接字 socket 概念

文章目录 &#x1f308; 一、IP 地址概念⭐ 1. IP 地址的作用⭐ 2. 源 IP 地址和目的 IP 地址 &#x1f308; 二、端口号概念⭐ 1. 源端口号和目的端口号⭐ 2. 端口号范围划分⭐ 3. 端口号 VS 进程 ID⭐ 4. 套接字 socket 的概念 &#x1f308; 三、传输层的典型代表协议⭐ 1. …

利用Docker Compose构建微服务架构

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 利用Docker Compose构建微服务架构 引言 Docker Compose 简介 安装 Docker Compose 创建项目结构 编写 Dockerfile 前端 Dockerf…

【Vue】一个案例带你学会组件通信!!!(1)(父传子props+子传父$emit)

嘿&#xff0c;开发者们&#x1f44b;&#xff01;欢迎来到今天的Vue.js组件通信大冒险。你是否曾在父子组件间的数据同步问题上感到头疼&#xff1f;&#x1f92f; 今天&#xff0c;我们将一起揭开Vue.js父子通信的神秘面纱&#xff0c;学习如何让数据在父子组件间流畅地“跳舞…

在VS中安装chatGPT

2、在VSCode中打开插件窗口 3、输入ChatGPT 4、这里有个ChatGPT中文版&#xff0c;就它了 5、安装 6、这时候侧边栏多了一个chatGPT分页图标&#xff0c;点击它 7、打个招呼 8、好像不行 9、看一下细节描述 10、根据要求按下按下快捷键 Ctrl Shift P 11、切换成国内模式 12、…

3. keil + vscode 进行stm32协同开发

1. 为什么使用vscode 主要还是界面友好&#xff0c;使用习惯问题&#xff0c;vscode 从前端&#xff0c;js, c/c, qt, 仓颉&#xff0c;rust都有很好插件的支持&#xff0c;并且有romote&#xff0c; wsl 等很多插件可以提高效率&#xff0c; 唯一的问题就是要使用插件进行环境…

PostgreSQL 学习笔记:PostgreSQL 主从复制

PostgreSQL 笔记&#xff1a;PostgreSQL 主从复制 博客地址&#xff1a;TMDOG 的博客 在现代应用程序中&#xff0c;数据库的高可用性和扩展性是至关重要的。PostgreSQL 提供了主从复制功能&#xff0c;可以在多个数据库实例之间复制数据&#xff0c;以实现冗余和负载均衡。本…

433、315通信、ev1527、2262编码

目录 ASK介绍EV1527编码芯片介绍模块介绍无线发射芯片无线接收芯片解码程序发射电路原理图 ASK介绍 ASK是幅移键控&#xff0c;通过调幅将数据发送出去&#xff0c;所以发送与接收都是多位二进制数。 ASK如何区分0和1&#xff1f; 0&#xff1a;发送 433.92Mhz 无线波形&…

Python 5个数据容器

列表&#xff08;list&#xff09; 特点&#xff1a;可以被修改 列表的定义 定义空列表&#xff1a; 变量名 [] 或 变量名 list() 定义变量&#xff1a; 变量名 [元素1&#xff0c;元素2&#xff0c;元素3&#xff0c;... ] 取出列表元素 列表名 [下标索引] 从前向…