[排序算法]堆排序

参考:《漫画算法-小灰的算法之旅》

目录

一、堆排序过程

二、堆排序的代码实现

三、时间复杂度和空间复杂度

四、从宏观上看,堆排序和快速排序相比,有什么区别和联系呢


回顾二叉堆: 

1.最大堆的堆顶是整个堆中的最大元素。 2.最小堆的堆顶是整个堆中的最小元素。

以最大堆为例,如果删除一个最大堆的堆顶(并不是完全删除,而是跟末尾的节点交换位置),经过自我调整,第2大的元素就会被交换上来,成为最大堆的新堆顶。

例如上图,在删除值为10的堆顶节点后,经过调整,值为9的新节点就会顶替上来;在删除值为9 的堆顶节点后,经过调整,值为8的新节点就会顶替上来…… 由于二叉堆的这个特性,每一次删除旧堆顶,调整后的新堆顶都是大小仅次于旧堆顶的节点。那么只要反复删除堆顶,反复调整二叉堆,所得到的集合就会成为一个有序集合。该过程就是堆排序。

一、堆排序过程

删除节点10,节点9会成为新的栈顶:

 删除节点9,节点8成为新堆顶。

删除节点8,节点7成为新堆顶。 

删除节点7,节点6成为新堆顶。 

 删除节点6,节点5成为新堆顶。

 删除节点5,节点4成为新堆顶。

 删除节点4,节点3成为新堆顶。 

删除节点3,节点2成为新堆顶。 

到此为止,原本的最大二叉堆已经变成了一个从小到大的有序集合。之前说过,二叉堆实际存储在数组中,数组中的元素排列如下。 

 由此,可以归纳出堆排序算法的步骤:

1、把无序数组构建成二叉堆。需要从小到大排序,则构建成最大堆;需要从大到小排序,则构建成最小堆。

2.循环删除堆顶元素,替换到二叉堆的末尾,调整堆产生新的堆顶。

二、堆排序的代码实现

using namespace std;
#include<iostream>
#include<string>
#include<vector>
//下沉调整
//parentIndex  要下沉的父节点
void downAdjust(vector<int>& array, int parentIndex, int length) {
	//temp保存父节点值,用于最后赋值
	int temp = array[parentIndex];
	int childIndex = 2 * parentIndex + 1;
	while (childIndex < length) {
		//如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子
		if (childIndex + 1 < length && array[childIndex + 1] > array[childIndex]) {
			childIndex++;
		}
		//如果父节点大于两个孩子节点的值,则直接跳出
		if (temp >= array[childIndex]) {
			break;
		}
		//无须真正交换,单向赋值即可
		array[parentIndex] = array[childIndex];
		parentIndex = childIndex;
		childIndex = 2 * parentIndex + 1;
	}
	array[parentIndex] = temp;
}
//堆排序(升序)
void heapSort(vector<int>& array) {
	//1、把无序数组构建成最大堆
	for (int i = (array.size() - 2) / 2; i >= 0; i--) {
		downAdjust(array, i, array.size());
	}
	//2、循环删除堆顶元素,移到集合尾部,调整堆产生新的堆顶
	for (int i = array.size() - 1; i > 0; i--) {
		//最后一个元素和第一个元素进行交换
		int temp = array[i];
		array[i] = array[0];
		array[0] = temp;
		//下沉调整最大堆
		downAdjust(array, 0, i);
	}
}

int main()
{
	vector<int> arr = { 1, 3, 2, 6, 5, 7, 8, 9, 10, 0 };
	heapSort(arr);
	for (int i = 0; i < arr.size(); i++) {
		cout << arr[i] << endl;
	}
	system("pause");
	return 0;
}

三、时间复杂度和空间复杂度

空间复杂度是O(1),因为并没有开 辟额外的集合空间。

二叉堆的节点“下沉”调整(downAdjust 方法) 是堆排序算法的基础,这个调节操作本身的时间复杂 度是O(log n)。 我们再来回顾一下堆排序算法的步骤。 1.把无序数组构建成二叉堆。 2.循环删除堆顶元素,并将该元素移到集合尾 部,调整堆产生新的堆顶。 第1步,把无序数组构建成二叉堆,这一步的时间 复杂度是O(n)。 第2步,需要进行n-1次循环。每次循环调用一次 downAdjust方法,所以第2步的计算规模是(n-1) ×logn,时间复杂度为O(nlogn)。 两个步骤是并列关系,所以整体的时间复杂度是 O(nlogn)。

四、从宏观上看,堆排序和快速排序相比,有什么区别和联系呢

先说说相同点,堆排序和快速排序的平均时间复 杂度都是O(nlogn),并且都是不稳定排序。至于不 同点,快速排序的最坏时间复杂度是O(n^2),而堆排序的最坏时间复杂度稳定在O(nlogn)。此外,快速排序递归和非递归方法的平均空间复 杂度都是O ( logn ) ,而堆排序的空间复杂度是 O(1)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot的外卖项目(详细开发过程)

基于SpringBootMyBatisPlus的外卖项目1、软件开发整体介绍软件开发流程角色分工2、外卖项目介绍项目介绍产品展示后台系统管理移动端技术选型功能结构角色3、开发环境的搭建开发环境说明建库建表Maven项目搭建项目的目录结构pom.xmlapplication.ymlReggieApplication启动类配置…

[JAVA]继承

目录 1.继承的概念 2.继承的语法 3.父类成员访问 3.1子类中访问父类成员变量 3.2子类中访问父类成员方法 4.super关键字 5.子类构造方法 6.继承方式 7.final关键字和类的关系 面向对象思想中提出了继承的概念&#xff0c;专门用来进行共性抽取&#xff0c;实现代码复…

2023年顶级编程语言趋势

对于开发人员和软件工程师来说&#xff0c;选择更优秀的编程语言使编写可以在任何地方运行的软件变得更加容易&#xff0c;工作效率更高。从 Java 的缓慢衰落到 MATLAB 的惊人流行&#xff0c;对当今最流行的编程语言的分析&#xff0c;可以帮助你了解最新趋势并响应最新趋势。…

总结:K8S运维常用命令

一、部署./kubectl apply -f biz-healing-pod.yaml 二、查看部署的资源1、podkubectl get pod -A&#xff1a;获取所有pod没有IP&#xff1f;用-o wide参数看详细信息&#xff1a;./kubectl get pod -n deepflow -o wide2、service查看hubble-manager命名空间下有哪些service/d…

Excel函数公式大全—函数真经

EXCEL系列文章目录 Excel系列文章是本人亲身经历职场之后萌发的想法&#xff0c;为什么Excel覆盖如此之广&#xff0c;几乎每个公司、学校、家庭都在使用&#xff0c;但是它深藏的宝藏功能却很少被人使用&#xff0c;PQ、BI这些功能同样适用于数据分析&#xff1b;并且在一些需…

ViewService——一种保证客户端与服务端同步的方法

简介在分布式系统中&#xff0c;最常见的场景就是主备架构。但是如果主机不幸宕机&#xff0c;如何正确的通知客户端当前后端服务器的状况成为一个值得研究的问题。本文描述了一种简单的模型用于解决此问题。背景以一个分布式的Key-Value数据库为背景。数据库对外提供3个接口Ge…

有哪些计算机网络和通讯领域的SCI期刊推荐? - 易智编译EaseEditing

IEEE/ACM Transactions on Networking: 这是由IEEE和ACM联合出版的计算机网络领域的顶级期刊&#xff0c;涵盖了网络协议、体系结构、性能评估、网络管理、安全等多个方面。 Computer Networks: 这是一本综合性的计算机网络期刊&#xff0c;包括分布式系统、网络协议、移动计…

Spring注册Bean的方式

文章目录一、xml方式注册Bean二、ConfigurationBean注册Bean三、ComponentScan注册Bean1. 使用XML文件配置包扫描2. 使用注解配置包扫描3. ComponentScans源码4. ComponentScan源码5. ComponentScan value includeFilters6. ComponentScan value excludeFilters7. Componen…

rabbitMQ介绍及使用方法

目录 一、MQ概述 二、RabbitMQ简介 三、RabbitMQ的五种工作模式 1、简单模式 2、work queues工作队列模式 3、Pub/Sub 订阅模式 4、Routing 路由模式 5、Topics 通配符模式 一、MQ概述 MQ全称Message Queue (消息队列)&#xff0c;是在消息的传输过程中保存消息的容器…

电商项目后端框架SpringBoot、MybatisPlus

后端框架基础 1.代码自动生成工具 mybatis-plus &#xff08;1&#xff09;首先需要添加依赖文件 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.2</version></dependency><de…

【linux】进程信号——信号的产生

进程信号一、信号概念1.1 信号理解二、产生信号2.1 通过键盘产生信号2.2 捕捉信号自定义signal2.3 系统调用接口产生信号2.3.1 向任意进程发送任意信号kill2.3.2 给自己发送任意信号raise2.3.3 给自己发送指定信号abort2.3.4 理解2.4 硬件异常产生信号2.4.1 除0异常2.4.2 野指针…

蓝桥杯刷题冲刺 | 倒计时17天

作者&#xff1a;指针不指南吗 专栏&#xff1a;蓝桥杯倒计时冲刺 &#x1f43e;马上就要蓝桥杯了&#xff0c;最后的这几天尤为重要&#xff0c;不可懈怠哦&#x1f43e; 文章目录1.长草2.分考场1.长草 题目 链接&#xff1a; 长草 - 蓝桥云课 (lanqiao.cn) 题目描述 小明有一…

Feign远程调用

之前在一篇博客中写了利用RestTemplate发起远程调用的代码&#xff0c;但是存在一下问题&#xff1a;代码可读性差&#xff0c;编程体验不统一&#xff1b;如果参数特别多的话&#xff0c;参数复杂URL难以维护。Feign官方地址&#xff1a;https://github.com/OpenFeign/feignFe…

行业观察 | 来了解一下AI加速器

本文参考网上可查询到的资料简要总结AI加速器的概念和应用等信息 1。 未完待续 更新&#xff1a; 2023 / 3 / 22 行业观察 | 来了解一下AI加速器前言加速器处理器处理器是什么&#xff1f;处理器进化史加速器架构指令集 ISA特定领域的指令集 ISA超长指令字&#xff08;VLIW&a…

如何使用子项目管理方案?

在项目进行中经常发生这样的情况&#xff1a;当你开始为一个项目制定时间表时&#xff0c;你会发现任务的数量太多。你需要把它们全部分组到一些摘要任务中。但随后你看到一堆摘要任务&#xff0c;也想把它们再分组。 这样一来&#xff0c;该项目变得很麻烦&#xff0c;甚至项目…

Matlab进阶绘图第10期—带填充纹理的柱状图

带填充纹理的柱状图是通过在原始柱状图的基础上添加不同的纹理得到的&#xff0c;可以很好地解决由于颜色区分不足而导致的对象识别困难问题。 由于Matlab中未提供纹理填充选项&#xff0c;因此需要大家自行设法解决。 本文使用Kesh Ikuma制作的hatchfill2工具&#xff08;Ma…

gin框架使用websocket实现进入容器内部执行命令

文章目录1. 先决条件2. gin框架实现3. 测试用html文件4. 需要完善1. 先决条件 docker开放远程API端口 2. gin框架实现 type GetCommandResultRequire struct {IpAddr string json:"ip_addr" //传入要控制容器的ip地址ContainerUuid string json:"cont…

对堆题的总体思路

浅说一下pwn堆并用一个简单的例子具体说明给刚入坑堆的小朋友说的一些思路说一下堆是什么堆你可以看成一个结构体数组&#xff0c;然后数组里每个元素都会开辟一块内存来存储数据那么这块用来存储数据的内存就是堆。结构体数组在BSS段上&#xff0c;其内容就是堆的地址&#xf…

动态SQL必知必会

动态SQL必知必会1、什么是动态SQL2、为什么使用动态SQL3、动态SQL的标签4、if 标签-单标签判断5、choose标签-多条件分支判断6、set 标签-修改语句7、foreach标签7.1 批量查询7.2 批量删除7.3 批量添加8、模糊分页查询1、什么是动态SQL 动态 SQL 是 MyBatis 的强大特性之一。如…

阿里巴巴2017实习生笔试题(二)——总结

具体题目来自阿里巴巴2017实习生笔试题&#xff0c;本文仅为整理与汇总。 本题应该往C的多态性进行理解&#xff0c;多态中的动态链接在执行时进行&#xff0c;静态链接在编译时进行。其中A、C、D 都是动态链接的优点&#xff0c;B 时静态链接的优点。 减少页面交换可从如下角…