堆排序的实现原理

一、什么是堆排序?

        堆排序就是将待排序元素以一种特定树的结构组合在一起,这种结构被称为堆。

        堆又分为大根堆和小根堆,所谓大根堆即为所有的父节点均大于子节点,但兄弟节点之间却没有什么严格的限制,小根堆恰恰相反,是所有的根节点均小于子节点。

        所以为了能够实现堆排序,第一个步骤就是将待排序的元素建成堆的形式,其次就是将建好的大根堆(小根堆)与堆的最后一个元素交换,然后再对新的堆进行向下的调整,但是在调整过程中,所有经过交换过的堆底元素不再进行新的调整,直到将倒数第二个元素调整完毕后结束。

        所以说堆排序虽说效率较高,但是它的算法步骤却不如其他排序那么明了,需要将它的每一个算法步骤了解清楚后,才能清晰的解析出来。

二、堆排序的算法步骤

        在排序家族中,堆排序是一种效率比较高的方法,它的 时间复杂度为O(nlogn),空间复杂度为O(1),它的主要排序步骤为:建堆、交换堆顶、堆底元素再向下调整。

        但是在此之前,我们需要先解析出两个分支算法,分别是向下调整和向上调整。

        顾名思义,向上(下)调整分别是从堆底(顶)为起始向堆顶(底)进行调整,目的则是严格维护堆的结构不被破坏。

        在本文的演示中,我们暂且以大根堆为例。

2.1向下调整

        首先,我们以【2,6,3,0,7】为例进行演示。

        我们先按照顺序构建堆,如下所示:

        然后我们建立两个int类型的变量parent和child,分别指向2和它的子节点,这里子节点的公式为(parent*2+1)。

        接下来就是要将parent所指的元素和child所指的元素进行比较,如果parent所指元素小于child所指元素则进行交换,再更新两个变量的位置,如果child所指元素不大于parent所指元素,则跳出循环。

                这样,一趟的向下调整就完成了,下面我们用代码实现:

//向下调整
void Modify_down(int parent , int end)
{int child = parent * 2 + 1;while (child <= end){if (child + 1 < end && _v[child] < _v[child + 1]){child++;}if (_v[child] > _v[parent]){swap(_v[parent], _v[child]);parent = child;child = child * 2 + 1;}elsebreak;}
}

2.2向上调整

        向上调整和向下调整有所不同,需要先找出其孩子节点中最大的那个,比较之后再进行交换操作,以【2,6,7,0,3】为例。

        调整过程中,计算父节点的计算方法为【(child-1)/2】,然后比较兄弟节点,找出最大的那个,如果孩子节点大于父节点,就进行交换,然后更换parent和child的下标位置,如果子节点小于父节点就跳出循环。代码如下:

//向上调整
void Modify_up(int child)
{int parent = (child - 1) / 2;while (child > 0){if (_v[child] > _v[parent]){swap(_v[parent], _v[child]);child = parent;parent = (child - 1) / 2;}elsebreak;}
}

2.3堆排序

        完成两个核心的算法后,我们最后只需将堆排序归纳一下即可。

1、建堆,将堆调整至合法。

//向上调整
void Modify_up(int child)
{int parent = (child - 1) / 2;while (child > 0){if (_v[child] > _v[parent]){swap(_v[parent], _v[child]);child = parent;parent = (child - 1) / 2;}elsebreak;}
}
//建堆
for (int i = 1; i < _v.size(); i++)
{Modify_up(i);
}

2、交换堆顶和堆底元素,然后再进行向下调整堆,在这里对于堆底的下标我们以变量“end”来控制,当end<=0时,则跳出循环。

//向下调整
void Modify_down(int parent , int end)
{int child = parent * 2 + 1;while (child <= end){if (child + 1 < end && _v[child] < _v[child + 1]){child++;}if (_v[child] > _v[parent]){swap(_v[parent], _v[child]);parent = child;child = child * 2 + 1;}elsebreak;}
}int end = _v.size() - 1;
while (end > 0)
{swap(_v[0], _v[end]);end--;Modify_down(0, end);
}

三、堆排序完整代码

class heapsort
{
public:heapsort(vector<int>& v):_v(v){}void heap_sort(){for (int i = 1; i < _v.size(); i++){Modify_up(i);}int end = _v.size() - 1;while (end > 0){swap(_v[0], _v[end]);end--;Modify_down(0, end);}}void Print(){for (int i = 0; i < _v.size(); i++){cout << _v[i] << " ";}}
protected://向上调整void Modify_up(int child){int parent = (child - 1) / 2;while (child > 0){if (_v[child] > _v[parent]){swap(_v[parent], _v[child]);child = parent;parent = (child - 1) / 2;}elsebreak;}}//向下调整void Modify_down(int parent , int end){int child = parent * 2 + 1;while (child <= end){if (child + 1 < end && _v[child] < _v[child + 1]){child++;}if (_v[child] > _v[parent]){swap(_v[parent], _v[child]);parent = child;child = child * 2 + 1;}elsebreak;}}
private:vector<int> _v;
};

四、、堆排序的适用场景

        堆排序适用于关键字较多的情况,如:在几亿个关键字中找出前十个最大的数据,我们只需建立小根堆,然后依次循环十次就能得到想要的数据了。

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

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

相关文章

Spring注解-@RestControllerAdvice

Spring注解-RestControllerAdvice RestControllerAdvice注解是什么 RestControllerAdvice是一个组合注解,由ControllerAdvice、ResponseBody组成。而ControllerAdvice又是由Component组合。使用RestControllerAdvice可用自定义一个异常处理类。一般配合ExceptionHandler、Init…

高通安卓12-在源码中查找应用的方法

1.通过搜索命令查找app 一般情况下&#xff0c;UI上看到的APP名称会在xml文件里面定义出来&#xff0c;如 搜索名字为WiGig的一个APP 执行命令 sgrep "WiGig" 2>&1|tee 1.log 将所有的搜索到的内容打印到log里面 Log里面会有一段内容 在它的前面是这段内…

Stable Diffusion部署教程,开启你的AI绘图之路

本文环境 系统&#xff1a;Ubuntu 20.04 64位 内存&#xff1a;32G 环境安装 2.1 安装GPU驱动 在英伟达官网根据显卡型号、操作系统、CUDA等查询驱动版本。官网查询链接https://www.nvidia.com/Download/index.aspx?langen-us 注意这里的CUDA版本&#xff0c;如未安装CUD…

CSS动画(动态导航栏)

1.项目简介 一个具有创意的导航菜单不仅能为你的大作业增色&#xff0c;还能展示你的技术实力。本文将分享一系列常用于期末大作业的CSS动画导航效果&#xff0c;这些效果不仅外观酷炫&#xff0c;而且易于实现。我们提供了一键复制的代码&#xff0c;让你能够快速集成到自己的…

掌握ChatGPT:提示工程入门详解

随着人工智能的发展&#xff0c;提示工程成为了使用ChatGPT等语言模型的核心技术。对于初学者&#xff0c;理解和运用提示工程是提高与ChatGPT互动效果的关键。 什么是提示工程&#xff1f; 提示工程是通过设计和优化输入文本&#xff08;提示&#xff09;来引导AI生成特定输出…

破碎的像素地牢探险:游戏分享

软件介绍 《破碎的像素地牢》是开源一款地牢冒险探索类的游戏&#xff0c;融合了日系RPG经典风格&#xff0c;玩家将控制主角进行未知场景的探索。除了经典地牢玩法外&#xff0c;游戏还添加了更多创意内容&#xff0c;如黑屏状态前的挑战性等&#xff0c;使得游戏更加富有挑战…

Vue78-缓存路由组件

一、需求 路由切走的时候&#xff0c;组件会被销毁&#xff0c;路由切回来&#xff0c;组件被挂载&#xff01; 需要&#xff1a;路由切走的时候&#xff0c;组件不会被销毁。 二、代码实现 若是不加include属性&#xff0c;则在<router-view>里面展示的路由&#xff0c…

ubuntu20.04安装配置openMVG+openMVS

安装 主要跟着官方教程逐步安装 openMVG https://github.com/openMVG/openMVG/blob/master/BUILD.md openMVS https://github.com/cdcseacave/openMVS/wiki/Building 注意事项 1. 库版本要求 使用版本&#xff1a; openMVS 2.2.0 openMVG Eigen 3.4.0 OpenCV 4.6.0 Ce…

华为开发者大会:全场景智能操作系统HarmonyOS NEXT

文章目录 一、全场景智能操作系统 - HarmonyOS NEXT1.1 系统特性1.2 关于架构、体验和生态 二、应用案例2.1 蚂蚁mpaas平台的性能表现 三、新版本应用框架发布3.1 新语言发布3.2 新数据库发布3.3 新版本编译器的发布 四、CodeArts和DataArts4.1 CodeArts4.2 DataArts 五、总结 …

高通安卓12-Input子系统

1.Input输入子系统架构 Input Driver(Input设备驱动层)->Input core(输入子系统核心层)->Event handler(事件处理层)->User space(用户空间) 2.getevent获取Input事件的用法 getevent 指令用于获取android系统中 input 输入事件&#xff0c;比如获取按键上报信息、获…

C++实现简单的哈希表

使用除留余数法计算哈希地址&#xff0c;使用拉链法解决哈希冲突&#xff0c;使用模板编程实现value为任意类型&#xff0c;但是key值只能是整型。链表使用CSTL库中的list&#xff0c;实现了一个简单的哈希表。 #include <iostream> #include <vector> #include &l…

Cloudflare 常用操作

一、域名托管到cloudflare 登录cloudflare->添加站点->填写域名(例如阿里云)->继续选择free套餐->继续->保存cloudflare分配的DNS地址->进入阿里云域名管理->进入DNS管理/DNS修改把DNS地址修改为cloudflare分配的两个DNS->保存->回到cloudflare->…

返利系统中的用户行为分析与推荐算法

返利系统中的用户行为分析与推荐算法 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在现代电子商务平台中&#xff0c;返利系统是一种重要的用户激励手段&am…

深入理解Python中的并发与异步的结合使用

​ 在上一篇文章中&#xff0c;我们讨论了异步编程中的性能优化技巧&#xff0c;并简单介绍了trio和curio库。今天&#xff0c;我们将深入探讨如何将并发编程与异步编程结合使用&#xff0c;并详细讲解如何利用trio和curio库优化异步编程中的性能。 文章目录 并发与异步编程的区…

【数据结构与算法】二叉树的性质 详解

在二叉树的第i层上至多有多少个结点。 在二叉树的第 i 层上至多有 2 i − 1 2^{i-1} 2i−1 个结点(i≥1)。 深度为 K的二叉树至多有多少个结点。 深度为 k 的二叉树上至多含 2 k − 1 2^k - 1 2k−1 个结点(k≥1)。 在一颗二叉树中, 其叶子结点数n0和度为二的结点数n2之间…

安装CDH时报错:Parcel 不可用于操作系统分配 RHEL7,原因与解决办法~

报错信息&#xff1a; 解决办法与思路&#xff1a; 1、检查CDH包的后缀名称&#xff0c;Redhat与Centos安装时不需要修改后缀名称&#xff0c;麒麟系统安装时才需要修改。 2、目录里面需要有xxx.parcel xxx.parcel.sha manifest.json 三个文件 缺一不可&#xff08;注&#x…

Transformer预测 | 基于Transformer的锂电池寿命预测(Pytorch,CALCE数据集)

文章目录 文章概述模型描述程序设计参考资料文章概述 Pytorch实现基于Transformer 的锂电池寿命预测,环境为pytorch 1.8.0,pandas 0.24.2 随着充放电次数的增加,锂电池的性能逐渐下降。电池的性能可以用容量来表示,故寿命预测 (RUL) 可以定义如下: SOH(t)=CtC0100%, 其中,…

JQuery 概念、历史、发展、优势-JQuery开发教程

一、JQuery 框架简介 jQuery 是一个 轻量级 JavaScript 库。 jQuery 极大地简化了 JavaScript 编程。 jQuery 很容易学习。 jQuery是一个快速、简洁的JavaScript框架&#xff0c;是继Prototype之后又一个优秀的JavaScript代码库&#xff08;框架&#xff09;于2006年1月由Joh…

@NotBlank、@NotNull、@NotEmpty、@NonNull四者之间的区别

文章目录 NotNullNotEmptyNotBlankNonNull NotNull 1.NotNull&#xff1a;用在基本类型上&#xff0c;不能为null&#xff0c;但可以为空字符串 NotEmpty 2.NotEmpty&#xff1a;用在集合类上&#xff0c;不能为null&#xff0c;并且长度必须大于0 NotBlank 3.NotBlank&am…

HarmonyOS Next 系列之可移动悬浮按钮实现(六)

系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现&#xff08;一&#xff09; HarmonyOS Next 系列之验证码输入组件实现&#xff08;二&#xff09; HarmonyOS Next 系列之底部标签栏TabBar实现&#xff08;三&#xff09; HarmonyOS Next 系列之HTTP请求封装和Token…