堆排序(C++实现)

参考:

  1. 面试官:请写一个堆排序_哔哩哔哩_bilibili
  2. C++实现排序算法_c++从小到大排序-CSDN博客

堆的基本概念

  1. 堆排实际上是利用堆的性质来进行排序。堆可以看做一颗完全二叉树

  2. 堆分为两类:

    1. 最大堆(大顶堆):除根节点外,堆的每个父节点都大于其孩子节点。
    2. 最小堆(小顶堆):除根节点外,堆的每个父节点都小于其孩子节点。
    3. 最大堆和最小堆示意图:在这里插入图片描述
  3. 数据结构包含逻辑结构和存储结构,对于堆来说:

    1. 堆的逻辑结构是完全二叉树
    2. 堆的存储结构可以是链式存储,也可以是顺序存储。在堆排序中我们基于的存储结构是顺序存储
    3. 顺序存储示意图:(以最大堆为例)在这里插入图片描述

堆排序

  1. 堆排序主要分为三个步骤:
    1. 建堆
    2. 交换数据
    3. 重复步骤1,2
  2. 建堆。首先说说建堆,因为我们要对数组进行排序,这个数组里元素原本的排列是无规则的,为了能通过堆对数组进行排序,我们需要进行“建堆”操作,从而使得数组的排序符合堆的要求。根据上文可知,堆可以分为两种,一种是最大堆,另一种是最小堆。既然有两种堆,我们应该基于哪种类别来建堆呢?这就要取决于我们的排序形式了,如果是升序(从小到大),则需要建最大堆;如果是降序(从大到小),则需要建最小堆。以下都以升序(建最大堆为例)。
  3. 交换数据。交换什么数据呢?这里直接给出结论,是交换堆(数组)索引为0的元素和末尾元素(堆的最后一个元素)。因为我们已经建好堆了,且我们堆的存储结构是顺序结构,即根节点(只最大的节点)存储在数组的第一位(索引为0),这是我们将这个数与数组最后一个数交换位置,就完成了数组中最大元素的排序(因为最大的元素肯定在数组最后一个位置)。
  4. 交换完数据后,对于新的堆(新的二叉树)来说,是不满足最大堆的条件的(因为发生了位置交换),这时就需要重新建堆,重新建堆有别于初次建堆,因为我们已经固定了最大元素的位置,所以之后建堆不应该让这个最大的元素参与进来。
  5. 参考代码如下:
    最大堆建堆
/*** 堆化* 大根堆(大顶堆/最大堆),小的数往下沉*/
void maxHeapify(vector<int> &nums, int pos, int len)
{// (pos << 1) + 1就是2*pos+1,对应该节点的左子节点// (pos << 1) + 2就是2*pos+2,对应该节点的右子节点int child = (pos << 1) + 1;while (child < len){if (child + 1 < len && nums[child + 1] > nums[child]){child = child + 1;}if (nums[pos] > nums[child]){return;}else{swap(nums[pos], nums[child]);pos = child;child = (pos << 1) + 1;}}
}

最小堆建堆

/*** 堆化* 小根堆(小顶堆/最小堆),大的数往下沉*/
void minHeapify(vector<int> &nums, int pos, int len)
{// (pos << 1) + 1就是2*pos+1,对应该节点的左子节点// (pos << 1) + 2就是2*pos+2,对应该节点的右子节点int child = (pos << 1) + 1;while (child < len){if (child + 1 < len && nums[child + 1] < nums[child]){child = child + 1;}if (nums[pos] < nums[child]){return;}else{swap(nums[pos], nums[child]);pos = child;child = (pos << 1) + 1;}}
}

堆排序

/*** 堆排序*/
void heapSort(vector<int> &nums)
{// 每次交换完数据后要len--,让排序好的元素不参与建堆for (int len = nums.size(); len > 0; len--){// (len - 2) >> 1就是(len-2)/2,这样能找到最后一个非叶子结点for (int i = (len - 2) >> 1; i >= 0; i--){minHeapify(nums, i, len);// 最小堆建堆,对应降序// maxHeapify(nums, i, len);// 最大堆建堆,对应升序}// 每进行一次交换就要重新堆化,且重新堆化时堆的大小要对应减1(因为堆末尾的元素已经排好序了)swap(nums[0], nums[len - 1]);}
}

堆排序测试用例

#include <iostream>
#include <vector>using namespace std;/*** 堆化* 大根堆(大顶堆/最大堆),小的数往下沉*/
void maxHeapify(vector<int> &nums, int pos, int len)
{int child = (pos << 1) + 1;while (child < len){if (child + 1 < len && nums[child + 1] > nums[child]){child = child + 1;}if (nums[pos] > nums[child]){return;}else{swap(nums[pos], nums[child]);pos = child;child = (pos << 1) + 1;}}
}/*** 堆化* 小根堆(小顶堆/最小堆),大的数往下沉*/
void minHeapify(vector<int> &nums, int pos, int len)
{int child = (pos << 1) + 1;while (child < len){if (child + 1 < len && nums[child + 1] < nums[child]){child = child + 1;}if (nums[pos] < nums[child]){return;}else{swap(nums[pos], nums[child]);pos = child;child = (pos << 1) + 1;}}
}/*** 堆排序*/
void heapSort(vector<int> &nums)
{for (int len = nums.size(); len > 0; len--){for (int i = (len - 2) >> 1; i >= 0; i--){minHeapify(nums, i, len);// 最小堆建堆,对应降序// maxHeapify(nums, i, len);// 最大堆建堆,对应升序}// 每进行一次交换就要重新堆化,且重新堆化时堆的大小要对应减1(因为堆末尾的元素已经排好序了)swap(nums[0], nums[len - 1]);}
}int main(int argc, char const *argv[])
{vector<int> nums = {5, 3, 2, 63, 56, 8, -1, 3, 0, -222};heapSort(nums);for (auto num : nums){cout << num << " ";}cout << endl;return 0;
}

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

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

相关文章

Java-IO流使用场景

Java IO 流是Java编程中非常重要的组成部分,用于处理文件读写、网络通信等数据传输任务。 1. 字节流 1.1 读取文件 import java.io.FileInputStream; import java.io.IOException;public class ReadFileExample {public static void main(String[] args) {try (FileInputSt…

Unity实现自定义图集(一)

以下内容是根据Unity 2020.1.0f1版本进行编写的   Unity自带有图集工具,包括旧版的图集(设置PackingTag),以及新版的图集(生成SpriteAtlas)。一般来说,unity自带的图集系统已经够用了,但是实际使用上还是存在一些可优化的地方,例如加载到Canvas上的资源,打图集不能…

PyQt 入门教程(3)基础知识 | 3.2、加载资源文件

文章目录 一、加载资源文件1、PyQt5加载资源文件2、PyQt6加载资源文件 一、加载资源文件 常见的资源文件有图像与图标&#xff0c;下面分别介绍下加载资源文件的常用方法 1、PyQt5加载资源文件 2、PyQt6加载资源文件 PyQt6版本暂时没有提供pyrcc工具&#xff0c;下面介绍下在不…

雷池社区版本SYSlog使用教程

雷池会对恶意攻击进行拦截&#xff0c;但是日志都在雷池机器上显示 如何把日志都同步到相关设备进行统一的管理和分析呢&#xff1f; 如需将雷池攻击日志实时同步到第三方服务器, 可使用雷池的 Syslog 外发 功能 启用 Syslog 外发 进入雷池 系统设置 页面, 配置 Syslog 设置…

北京京恋在喧嚣的都市中助你邂逅自己的爱情

北京的夜晚&#xff0c;灯火璀璨&#xff0c;车水马龙。刘凡站在他位于国贸的公寓阳台上&#xff0c;望着眼前熙熙攘攘的街道&#xff0c;心中却有一丝落寞。32岁的他&#xff0c;是一家知名互联网公司的中层管理&#xff0c;事业有成&#xff0c;收入稳定&#xff0c;甚至朋友…

anaconda(jupyter)安装教程

目录 一、下载anaconda安装包 二、安装程序 三、怎么使用 四、把jupyter界面语言修改成中文 一、下载anaconda安装包 anaconda官网&#xff1a;下载 Anaconda Distribution |蟒蛇 清华大学开源软件镜像站官网&#xff1a;清华大学开源软件镜像站 | Tsinghua Open Source M…

嵌入式linux中条件变量的具体实现

大家好,今天主要给大家分享一下,如何使用条件变量以及具体实现方法。 第一:条件变量分析 条件变量是另一种逻辑稍微复杂一点点的同步互斥机制,他必须跟互斥锁一起配合使 他的应用场景也是非常常见的,先来看一个例子: 用,小楠是一名在校学生,每个月都会从父母那里得到一笔…

考研C语言程序设计_语法相关(持续更新)

目录 一、语法题strlen转义字符内置数据类型字符串结束标志局部变量和全局变量名字冲突 局部优先switch语句中的关键字数组初始化是否正确注意define不是关键字C语言中不能用连等判断switch( )的括号里可以是什么类型?关于if关于switch关于while 二、程序阅读题有关static有关…

【openGL学习笔记】----GLFW、GLAD环境配置

glew、glad、freeglut、glfw的区别&#xff1f; glew&#xff08;The OpenGL Extension Wrangler Library&#xff09;是对底层OpenGL接口的封装&#xff0c;可以让你的代码跨平台。glad与glew作用相同&#xff0c;可以看作它的升级版。Freeglut&#xff08;OpenGL Utility To…

计算机组成原理(笔记7高速缓冲存储器Cache,计算机组成原理的重难点全、直接、组相连)

为什么要设立高速缓冲存储器 &#xff08;Cache&#xff09;&#xff1f; Cache是介于CPU和主存之间的小容量存储器&#xff0c;存取速度比主存快。它能高速地向CPU提供指令和数据&#xff0c;加快程序的执行速度。它是为了解决CPU和主存之间速度不匹配而采用的一项重要技术。…

使用Mockaroo生成测试数据

使用Mockaroo生成测试数据 最近在学习【Spring Boot & React】Spring Boot和React教程视频的P51.Generating 1000 students一课中&#xff0c;看到了https://www.mockaroo.com/网站可以用来模拟生成测试数据&#xff0c;觉得还不错&#xff0c;特此记录一下。感觉每次看老…

centOS部署Jenkins实现项目可持续自动化部署

个人看的是尚硅谷的视频&#xff0c;跟着实战&#xff0c;但因为视频是21年的&#xff0c;所以很容易出现jenkins插件不适配问题。 因而个人直接用较新版的jdk和jenkins. 先切换到root用户 sudo su一、安装jdk 先查询可安装版本 yum list java*安装jdk&#xff08;只复制圈…

【Python爬虫实战】正则:中文匹配与贪婪非贪婪模式详解

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、匹配中文 &#xff08;一&#xff09;匹配单个中文字符 &#xff08;二…

DeepFM模型代码详解

直到看到这篇文章&#xff0c;我才搞明白类别特征怎么做lookup的&#xff0c;也看明白了代码逻辑。如果你看完没懂&#xff0c;私信留下wx&#xff0c;给你讲懂。 1、Deepfm 的原理&#xff0c;DeepFM 是一个模型还是代表了一类模型&#xff0c;DeepFM 对 FM 做了什么样的改进…

单细胞copyKat分析学习和整理

CopyKAT(肿瘤拷贝数核型分析)是一种使用综合贝叶斯方法的计算工具&#xff0c;能够在单细胞中以5MB分辨率检测全基因组非整倍体&#xff0c;以便从高通量单细胞RNA测序数据中区分肿瘤细胞与正常细胞&#xff0c;并识别肿瘤亚克隆。 (这里提一下,“5MB”是指 5兆碱基对(5 megab…

CTF-PWN方向 栈溢出等基础知识笔记(2)

C语言基本函数补充 write函数 ret2syscall 要求有0x80这种系统调用存在 &#xff08;0x0A是回车的意思&#xff09; 案例 通过file查看这个文件 发现是静态编译的文件 所以很多库函数都被编译进去了 但是不存在bin/sh字符串 不存在system和backdoor函数 修改&#xff0c;rea…

【环境搭建】远程服务器搭建ElasticSearch

参考&#xff1a; 非常详细的阿里云服务器安装ElasticSearch过程..._阿里云服务器使用elasticsearch-CSDN博客 服务器平台&#xff1a;AutoDL 注意&#xff1a; 1、切换为非root用户&#xff0c;su 新用户名&#xff0c;否则ES无法启动 2、安装过程中没有出现设置账号密码…

AD9361 在低至 1MHz 的频率下运行

AD9361 在低至 1MHz 的频率下运行 AD -FREQCVT1-EBZ是包含AD9361的FMCOMMS3/4/5板的附加板。虽然完整的芯片级设计包可在此 RF 收发器的ADI产品页面上找到&#xff0c;但有关此卡的信息及其使用方法、围绕它的设计包以及可使其工作的软件可在此处找到。 AD-FREQCVT1-EBZ 模块…

山西农业大学20241015

02-VUE 一. Vue中常用的指令1. Vue指令概述2 Vue中指令的分类3 Vue中指令3.1 内容渲染指令3.2 条件渲染指令3.2.1 v-show3.2.2 v-if3.2.3 v-else 和 v-else-if 3.3 事件绑定指令 v-on--重要3.3.1 内联语句3.3.2 methods中的函数名 一. Vue中常用的指令 1. Vue指令概述 概念: 指…

安装Node.js环境,安装vue工具

一、安装Node.js 去官方网站自行安装自己所需求的安装包 这是下载的官方网站 下载 | Node.js 中文网 给I accept the terms in the License Agreement打上勾然后点击Next 把安装包放到自己所知道的位置,后面一直点Next即可 等待它安装好 然后winr打开命令提示符cmd 二、安装…