堆排序(C++实现)
参考:
- 面试官:请写一个堆排序_哔哩哔哩_bilibili
- C++实现排序算法_c++从小到大排序-CSDN博客
堆的基本概念
-
堆排实际上是利用堆的性质来进行排序。堆可以看做一颗完全二叉树。
-
堆分为两类:
- 最大堆(大顶堆):除根节点外,堆的每个父节点都大于其孩子节点。
- 最小堆(小顶堆):除根节点外,堆的每个父节点都小于其孩子节点。
- 最大堆和最小堆示意图:
-
数据结构包含逻辑结构和存储结构,对于堆来说:
- 堆的逻辑结构是完全二叉树
- 堆的存储结构可以是链式存储,也可以是顺序存储。在堆排序中我们基于的存储结构是顺序存储。
- 顺序存储示意图:(以最大堆为例)
堆排序
- 堆排序主要分为三个步骤:
- 建堆
- 交换数据
- 重复步骤1,2
- 建堆。首先说说建堆,因为我们要对数组进行排序,这个数组里元素原本的排列是无规则的,为了能通过堆对数组进行排序,我们需要进行“建堆”操作,从而使得数组的排序符合堆的要求。根据上文可知,堆可以分为两种,一种是最大堆,另一种是最小堆。既然有两种堆,我们应该基于哪种类别来建堆呢?这就要取决于我们的排序形式了,如果是升序(从小到大),则需要建最大堆;如果是降序(从大到小),则需要建最小堆。以下都以升序(建最大堆为例)。
- 交换数据。交换什么数据呢?这里直接给出结论,是交换堆(数组)索引为0的元素和末尾元素(堆的最后一个元素)。因为我们已经建好堆了,且我们堆的存储结构是顺序结构,即根节点(只最大的节点)存储在数组的第一位(索引为0),这是我们将这个数与数组最后一个数交换位置,就完成了数组中最大元素的排序(因为最大的元素肯定在数组最后一个位置)。
- 交换完数据后,对于新的堆(新的二叉树)来说,是不满足最大堆的条件的(因为发生了位置交换),这时就需要重新建堆,重新建堆有别于初次建堆,因为我们已经固定了最大元素的位置,所以之后建堆不应该让这个最大的元素参与进来。
- 参考代码如下:
最大堆建堆:
/*** 堆化* 大根堆(大顶堆/最大堆),小的数往下沉*/
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;
}
相关文章:

堆排序(C++实现)
参考: 面试官:请写一个堆排序_哔哩哔哩_bilibiliC实现排序算法_c从小到大排序-CSDN博客 堆的基本概念 堆排实际上是利用堆的性质来进行排序。堆可以看做一颗完全二叉树。 堆分为两类: 最大堆(大顶堆):除根…...

Qt中加入UI文件
将 UI 文件整合到 Qt 项目 使用 Qt Designer 创建 UI 文件: 在 Qt Creator 中使用 Qt Designer 创建 UI 文件,设计所需的界面。确保在设计中包含所需的控件(如按钮、文本框等),并为每个控件设置明确的对象名称…...

Redisson使用全解
redisson使用全解——redisson官方文档注释(上篇)_redisson官网中文-CSDN博客 redisson使用全解——redisson官方文档注释(中篇)-CSDN博客 redisson使用全解——redisson官方文档注释(下篇)_redisson官网…...

Go4 和对 Go 的贡献
本篇内容是根据2017年4月份Go4 and Contributing to Go音频录制内容的整理与翻译, Brad Fitzpatrick 加入节目谈论成为开源 Go 的代言人、让社区参与 bug 分类、Go 的潜在未来以及其他有趣的 Go 项目和新闻。 过程中为符合中文惯用表达有适当删改, 版权归原作者所有. Erik St…...

区间动态规划
区间动态规划(Interval DP)是动态规划的一种重要变种,特别适用于解决一类具有区间性质的问题。典型的应用场景是给定一个区间,要求我们在满足某些条件下进行最优划分或合并。本文将从区间DP的基本思想、常见问题模型以及算法实现几…...

什么情况下需要使用电压探头
高压探头是一种专门设计用于测量高压电路或设备的探头,其作用是在电路测试和测量中提供安全、准确的信号捕获,并确保操作人员的安全。这些探头通常用于测量高压电源、变压器、电力系统、医疗设备以及其他需要处理高电压的设备或系统。 而高压差分探头差分…...

数据结构——八大排序(下)
数据结构中的八大排序算法是计算机科学领域经典的排序方法,它们各自具有不同的特点和适用场景。以下是这八大排序算法的详细介绍: 五、选择排序(Selection Sort) 核心思想:每一轮从未排序的元素中选择最小࿰…...

Linux系统:Ubuntu上安装Chrome浏览器
Ubuntu系统版本:23.04 在Ubuntu系统上安装Google Chrome浏览器,可以通过以下步骤进行: 终端输入以下命令,先更新软件源: sudo apt update 或 sudo apt upgrade终端输入以下命令,下载最新的Google Chrome .…...

Redis位图BitMap
一、为什么使用位图? 使用位图能有效实现 用户签到 等行为,用数据库表记录签到,将占用很多存储;但使用 位图BitMap,就能 大大减少存储占用 二、关于位图 本质上是String类型,最小长度8位(一个字…...

YOLOv11改进策略【卷积层】| ParNet 即插即用模块 二次创新C3k2
一、本文介绍 本文记录的是利用ParNet中的基础模块优化YOLOv11的目标检测网络模型。 ParNet block是一个即插即用模块,能够在不增加深度的情况下增加感受野,更好地处理图像中的不同尺度特征,有助于网络对输入数据更全面地理解和学习,从而提升网络的特征提取能力和分类性能…...

学习threejs,网格深度材质MeshDepthMaterial
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️网格深度材质MeshDepthMate…...

算法时间、空间复杂度(二)
目录 大O渐进表示法 一、时间复杂度量级的判断 定义: 例一:执行2*N+1次 例二:执行MN次 例三:执行已知次数 例四:存在最好情况和最坏情况 顺序查找 冒泡排序 二分查找 例五:阶乘递归 编辑 例…...

高级java每日一道面试题-2024年10月11日-数据库篇[Redis篇]-Redis都有哪些使用场景?
如果有遗漏,评论区告诉我进行补充 面试官: Redis都有哪些使用场景? 我回答: Redis 是一个开源的、基于键值对的数据结构存储系统,,它支持多种数据类型,包括字符串、散列、列表、集合和有序集合。它可以用作数据库、缓存和消息中间件。由于…...

0047__【python打包分发工具】setuptools详解
【python打包分发工具】setuptools详解-CSDN博客...

自定义拦截器处理token
目录 1、WebConfig 配置类 2、TSUserContext 把用户信息放到context中 3、自定义拦截器 4、在controller中可以使用 5、参考链接 1、WebConfig 配置类 @Configuration public class WebConfig implements WebMvcConfigurer {@Autowiredprivate AccessControlInterceptor …...

Scrapy | 使用Scrapy进行数据建模和请求
scrapy数据建模与请求 数据建模1.1 为什么建模1.2 如何建模1.3如何使用模板类1.4 开发流程总结 目标: 1.应用在scrapy项目中进行建模 2.应用构造Request对象,并发送请求 3.应用利用meta参数在不同的解析函数中传递数据 数据建模 | 通常在做项目的过程中…...

学习笔记——交换——STP(生成树)基本概念
三、基本概念 1、桥ID/网桥ID (Bridege ID,BID) 每一台运行STP的交换机都拥有一个唯一的桥ID(BID),BID(Bridge ID/桥ID)。在STP里我们使用不同的桥ID标识不同的交换机。 (2)BID(桥ID)组成 BID(桥ID)组成(8个字节):由16位(2字节)的桥优先级…...

机器学习笔记-2
文章目录 一、Linear model二、How to represent this function三、Function with unknown parameter四、ReLU总结、A fancy name 一、Linear model 线性模型过于简单,有很大限制,我们需要更多复杂模式 蓝色是线性模型,线性模型无法去表示…...

SpringSecurity(一)——认证实现
一、初步理解 SpringSecurity的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。 当前系统中SpringSecurity过滤器链中有哪些过滤器及它们的顺序。 核心过滤器: (认证)UsernamePasswordAuthenticationFilter:负责处理…...

VMWare NAT 模式下 虚拟机上不了网原因排查
vmware 按照了Linux之后 无法上网,搞定后,记录一些信息。 window有两个虚拟网卡 VMnet1 对应的是 Host-Only(仅主机模式) VMnet8 对应的是 NAT(网络地址转换模式) 在NAT模式中,需要设置NAT和D…...

R语言手工实现主成分分析 PCA | 奇异值分解(svd) 与PCA | PCA的疑问和解答
几个问题: pca可以用相关系数矩阵做吗?效果比协方差矩阵比怎么样?pca做完后变量和样本的新坐标怎么旋转获得?pca做不做scale和center对结果有影响吗?pca用因子分解和奇异值分解有啥区别?后者怎么获得变量和样本的新坐标?1. 用R全手工实现 PCA(对比 prcomp() ) 不借助包…...

第三届OpenHarmony技术大会在上海成功举办
10月12日,以“技术引领筑生态,万物智联创未来”为主题的第三届OpenHarmony技术大会(以下简称“大会”)在上海成功举办。本次大会由OpenAtom OpenHarmony(以下简称“OpenHarmony”)项目群技术指导委员会&…...

数字化:IT部门主导还是业务部门主导?
在这个瞬息万变的数字化时代,企业如同在大海中航行的小船,面对波涛汹涌的市场竞争,数字化转型已成为生存的必经之路。然而,在这条充满挑战的航线上,常常会出现一个让人纠结的问题:数字化转型究竟应该由IT部…...

MySQL表的基本查询下/分组聚合统计
1,update 对查询到的结果进行列值更新,可以和older by,where,limit合并使用,为了方便讲解,将会以题目练习的方式进行说明: 1,将孙悟空同学的数学成绩变更为 80 分 本道题和where联…...

条款3: 理解decltype
目录 一、decltype + 变量 二、decltype + 表达式 三、decltype 使用场景 一、decltype + 变量 🥭 所有的信息都会保留,数组和函数也不会退化 const int &&carref = std::move(ca); decltype(carref) bb; // bb推导为const int &&,不会被忽略掉co…...

TCP:过多的TIME_WAIT
过多的TIME_WAIT 线上问题紧急处理方式tcp_tw_reuse启用主要特点:源码 线上问题 线上机器出现了几万个TIME_WAIT,怎么办? 紧急处理方式 tcp_tw_reuse 启用 默认情况下tcp_tw_reuse是关闭状态,使用sysctl -w net.ipv4.tcp_tw_…...

化学元素分子量、氧化物系数计算python类
在网上找到的分子量计算类,做了少量修改,有原子量、分子量、氧化物系数的计算。 import re wt_dict{ #该原子量数据从CRC手册第95版提取。"H": 1.008,"He": 4.002602,"Li": 6.94,"Be": 9.0121831,"B": 10.…...

torch.utils.data.DataLoader参数介绍
torch.utils.data.DataLoader 是 PyTorch 用于加载数据的重要工具,特别是在深度学习模型训练中。它可以高效地处理大规模数据集,并支持多线程数据加载。以下是 DataLoader 的关键参数及其功能: 主要参数 dataset: 要加载的数据集,可以是 PyTorch 自带的 torch.utils.data.…...

echarts 入门
工作中第一次碰到echarts,当时有大哥。二进宫没办法,只能搞定它。 感觉生活就是这样,不能解决的问题总是会反复出现。通过看视频、查资料,完成了工作要求。写一篇Hello World,进行备查。 基本使用 快速上手 <!DO…...

WPF实现类似网易云音乐的菜单切换
这里是借助三方UI框架实现了,感兴趣的小伙伴可以看一下。 深色模式: 浅色模式: 这里主要使用了以下三个包: MahApps.Metro:UI库,提供菜单导航和其它控件 实现步骤:1、使用B…...