堆排序(大根堆与小根堆)

news2024/10/7 14:27:12

(1)是什么?

是一种适用于关键字较多的情况下的排序算法,例如在十亿个数中选出前1000个最大值或者最小值
如果在传统的排序算法中(例如冒泡,插入等),我们习惯把目标数据整体进行一次排序,再截取出前1000个最小的或者最大的。
但是我们可以设想一下,从一开始我们目标就只要1000个,那么其实其余九亿九千九百九十九万九千个数据,我们压根不需要知道它们的排序顺序,只需要知道它们都比我们1000个目标数据中最大值都要大就可以了
这就是堆排序。

它的思想整体上非常清晰简单,结构上是一个完全二叉树。
根结点比左右孩子都大则叫做大根堆。其中,左右孩子的根结点,又会比它们的左右孩子都大。
根结点比左右孩子都小则叫做小根堆。其中,左右孩子的根结点,又会比它们的左右孩子都小。
更简单点说:所有中间结点,一定比它孩子大(大根堆),或者一定比它的孩子小(小根堆)

(2)如何构建大根堆

初始化:

1:按照给出的数组,首先按照层次优先(逐层摆放)构造一棵二叉树
2:从该二叉排序树的最后一个叶子结点的根结点出发,比较该结点的左右孩子,选取最大的置换到根结点上
3:整理倒数第二非叶子结点,比较并选择一个最大的置换到根结点…
4:依次类推,直到整理完整棵树,此时树的根结点一定是该大根堆中最大值
5:在把大数往上顶的过程中,也要看互换位置的数是否比左右孩子都大,如果不是,则又要选择一个最大的换到该子树根结点。

例如:假设有数组【1,3,5,7,9,2,4,6,8,10】要求建立大根堆

1:先按照层次优先原则建立二叉树(该树生成后默认按照行遍历存放在一个一维数组中,且该数组下标从1开始,即下标为1存放着根结点1,下标2存放左孩子2,下标3存放着右孩子5,以此类推)
在这里插入图片描述

2:从该二叉树的最后一个非叶子结点出发,比较该结点的左右孩子,选取最大的置换到根结点上
如何找到二叉树最后一个非叶子结点:n/2向下取整
该例子中,10个元素,则10/2 = 5;即最后一个非叶子结点下标是5,也就是根结点值为9的子树。
比较9,10,发现10最大,于是10和9交换位置。

3:整理倒数第二非叶子结点,比较并选择一个最大的置换到根结点…
如何找到倒数第二个非叶子结点:n/2 - 1 = 4
也就是下标为4的,根结点值为7的子树
比较6,7,8,于是7和8交换位置,8作为根结点。

4:依次类推,直到整理完整棵树,此时树的根结点一定是该大根堆中最大值
5:在把大数往上顶的过程中,也要看互换位置的数是否比左右孩子都大,如果不是,则又要选择一个最大的换到该子树根结点。
在这里插入图片描述

到这里就完成了大根堆的构建

输出栈顶元素:

当输出栈顶的10后,固定用【最后一个叶子结点】1补上,发现1破坏了大根堆的性质,于是要从根结点往下调整,也就是比较1,9,5;把9放根结点。
1下沉到左子树根结点,但是还是不满足大根堆性质,于是比较1,8,3;把8放到左子树根结点,1再次下沉到左子树的左子树的根结点中
比较1,6,7;把7替换到左子树的左子树的根结点,把1再次下沉。
至此,重新调整的二叉树又符合大根堆性质了。
在这里插入图片描述

新增/插入元素操作:

新增/插入的元素都是把新结点放在新生成的最后一个叶子结点中,然后比较该新叶子结点数据的值与它父结点的值的大小,看是否需要换位置,如果需要,则开始调整,这跟初始化时候一样的操作。

⚠️注意,初始化和新增元素都是由下至上的调整,而删除了栈顶元素,是由上至下的调整。

代码实现:

#include <stdio.h>

void HeapSort(int a[], int i, int lenght){
	/*用以保存子树的根结点*/
	a[0] = a[i];
	/* 按照二叉树性质,不断i*2是不断深入找到下一层的左孩子结点 */
	for(int j=i*2; j<=lenght; j=j*2){
		/* k是对应子树的右孩子结点,先比较右孩子 */
		int k = j+1; 
		/* 左右孩子比较出一个大值 */
		if(k<lenght && a[k]>a[j]){
			j = k;
		}
	    /* 判断根结点与左右孩子的最大值谁更大 */
		if(a[0]<a[j]){
			a[i] = a[j];
			i = j;
		}
	}
	/* 循环退出后,j一定是最适合temp值的地方 */
	a[i] = a[0];
}

int main()
{
	int a[]={0,1,3,5,7,9,2,4,6,8,10};
	int lenght = 11;
	/* 从下往上逐个非叶子结点调整 */
	for(int i=lenght/2; i>0; i--) {
		HeapSort(a,i,lenght);
	}
   
   return 0;
}


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

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

相关文章

Cisco ASA应用——NAT的类型

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.NAT的类型 1.动态NAT 2.静态NAT 3.静态PAT 4.动态PAT 前言…

爱奇艺:基于龙蜥与 Koordinator 在离线混部的实践解析

在 2022 云栖大会龙蜥峰会云原生专场上&#xff0c;来自爱奇艺的基础架构研究员赵慰分享了《基于龙蜥与 Koordinator 的在离线混部实践》技术演讲&#xff0c;以下为本次演讲内容&#xff1a; 一、爱奇艺离线业务混部背景 与众多互联网公司一样&#xff0c;爱奇艺常见的负载类…

WSN final fighting 12.05

0.网络时间协议(NTP) p54 1.Min-Max定位 p63 2.质心算法定位 p64 3.覆盖修复过程 p95 4.数据融合的卡尔曼滤波法 p72 5.数据融合的神经网络算法 p73 6.TMAC协议 p135 7.基于分分簇网络的MAC协议 p140 8.蓝牙协议 p170 9.GEM路由协议 p206 10.MECN路由协议 p206 11.阐…

INTERSPEECH 2022——基于层级上下文语义信息的多尺度语音合成风格建模

本文由清华大学与虎牙信息科技有限公司、元象唯思控股&#xff08;深圳&#xff09;有限公司和香港中文大学合作。 人类语音的风格表达是多尺度的&#xff0c;不仅包括全局尺度的情感表达&#xff0c;还包括局部尺度的韵律表达。 而现有关于表现力语音合成的工作只考虑了单一尺…

C++ 静态成员变量与静态成员函数

在C的类中&#xff0c;有静态成员变量和静态成员函数 #include <iostream> #include <string>using namespace std;class test { private:static int m_value; //定义类的静态成员变量public:static int getValue() //定义类的静态成员函数{return m_value;} };in…

Mybatis-Plus中的and和or用法

先看Mybatis-Plus官网中对这两个关键字用法的介绍 数据库文件&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1KzY32Jq0srDQU9m-a-YtBQ?pwdrsdg 提取码&#xff1a;rsdg 表数据&#xff1a; 比如我们想查age等于23并且school_id等于300的 sql语句为&#xff1a;select…

FL Studio 20音乐制作教程

FL Studio 20音乐制作教程 FL Studio 20 中的音乐制作 – 制作 3 首完整曲目 – 只需一天即可管理 FL Studio&#xff0c;音乐、混音和母带制作 课程英文名&#xff1a;FL Studio 20 Music Production In FL Studio for Mac & PC 此视频教程共20.0小时&#xff0c;中英双…

【C++11多线程】线程的创建、结束、传递参数

文章目录1.普通函数作为线程函数1.1 thread1.2 join()1.3 detach()1.4 joinable()2.函数对象作为线程函数3.lambda表达式作为线程函数4.类成员函数作为线程函数5.向线程函数传递参数1.普通函数作为线程函数 程序运行起来&#xff0c;生成一个进程&#xff0c;其中主线程从 mai…

毕业设计 基于单片机的地震探测器系统 - stm32 物联网 嵌入式

文章目录0 前言1 简介2 主要器件3 实现效果4 硬件设计3轴加速度计ADXL335ADXL335加速度计的工作原理电路图和连接5 部分核心代码最后0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕…

[附源码]计算机毕业设计基于Springboot物品捎带系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

拳头游戏教程

文章目录一、初谈游戏美术游戏美术师的作用视觉效果二、概念创造1.项目前期准备2.生成创意3.获取反馈三、角色设计从概念到3D模型3D建模的过程表面改变解剖学协作改变四、环境设计什么是环境美术创建的过程视觉层次可信度效率五、技术美术骨骼制作定制化工具移植开发流程shader…

模拟百度网盘

linux下基于多线程和tcp去实现了一个模拟网盘,实现cs之间的下载互传大文件,实现断点续传,秒传,利用md5进行校验,实时显示百分比 整体框架: 整个项目是在Linux环境下用C语言开发的,基于TCP协议,采用多线程的socket通信方式。 普通上传和秒传:客户端会先计算文件的MD…

(六)Vue之MVVC

文章目录MVVCVue中的MVVCVue代码中的MVVMVue学习目录 上一篇&#xff1a;&#xff08;五&#xff09;Vue之data与el的两种写法 MVVC MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。 MVC参考&#xff1a;MVC架构模式 MVVM 就是将其中的View 的状态和行为抽象…

YOLOv5实现车辆检测(含车辆检测数据集+训练代码)

YOLOv5实现车辆检测(含车辆检测数据集训练代码) 目录 YOLOv5实现车辆检测(含车辆检测数据集训练代码) 1. 前言 2. 车辆检测数据集说明 &#xff08;1&#xff09;车辆检测数据集 &#xff08;2&#xff09;自定义数据集 3. 基于YOLOv5的车辆检测模型训练 &#xff08;1…

【Python】-- Turtle绘图(使用代码画喜欢的图形!)

什么是Turtle&#xff1f; turtle库是Python语言中一个很流行的绘制图像的函数库&#xff0c;可以想象一个小乌龟在爬行&#xff0c;它的爬行轨迹就是绘制出来的图形&#xff0c;在一个横轴为x、纵轴为y的坐标系原点&#xff0c;(0,0)位置开始&#xff0c;它根据一组函数指令的…

罐头食品市场向好,APS车间排产软件保证食品制造企业有序生产

这些年&#xff0c;随着人们健康意识的不断提升&#xff0c;一些消费者认为&#xff0c;罐头的保质期长是因为添加了大量的防腐剂&#xff0c;但实际上这是一种错误的认知。罐头食品不需要添加防腐剂&#xff0c;而是采用热力杀菌和密封工艺&#xff0c;达到商业无菌和真空保存…

如何管好一个迭代?让数据帮你回答这些关键问题

对软件从业者来说&#xff0c;『敏捷开发』早已不是一个新名词。 相比瀑布模型&#xff0c;敏捷开发模型更强调演进式开发&#xff0c;快速灵活地应对变化&#xff0c;最终交付使客户满意的产品。这就要求研发团队内部、研发团队与产品乃至与业务、客户之间的密切沟通。当变化…

CW6163C车床的三维仿真及加工工艺

目录 1 传动轴分析 - 1 - 1.1 传动轴结构特点 - 1 - 1.2 传动轴的工艺分析 - 1 - 1.3 传动轴的技术要求 - 2 - 2 毛坯的选择 - 3 - 2.1 毛坯的类型 - 3 - 2.2 毛坯余量的确定 - 3 - 2.3 毛坯草图 - 4 - 3 工艺规程设计 - 5 - 3.1 定位基准的选择 - 5 - 3.1.1 粗基准的选择 - 5 …

div做一个简单的自适应布局

div做一个简单的自适应布局 效果 代码&#xff1a; <template><div class"main-page"><div></div><div></div><div></div><div></div><div></div></div> <style lang"le…

深入浅出——spring和AspectJ实现AOP操作

基本概念可看我之前的文章 AOP——基本概念、底层原理&#xff0c;这次直接来实现AOP的操作&#xff0c;在介绍操作之前&#xff0c;我们得先介绍AOP的各种术语 aop操作术语 1、连接点&#xff08;JoinPoint&#xff09;&#xff1a; 类里面哪些方法可以被增强&#xff0c;这…