排序——堆排序

本节继续复习排序算法。这次复习排序算法中的堆排序。 堆排序属于选择排序。

目录

什么是堆?

堆排序

堆排序的思想

堆排代码

向下调整算法

 堆排整体


什么是堆?

在复习堆排序之前, 首先我们需要回顾一下什么是堆 。

堆的本质其实是一个数组。 它的物理结构本质上是一个数组。 但是它的逻辑结构是一棵完全二叉树。我们在判断一个数组是否是一个堆的时候根据的就是它的逻辑结构。

那么怎么根据它的逻辑结构判断是否是一个堆。 

首先堆的逻辑结构的二叉树的每一个孩子节点都大于它的每一个父亲, 就是堆。 这种堆叫做小堆。 如果它的逻辑结构的每一个孩子节点都小于它的父亲节点。 它同样是个堆, 同时这种堆叫做大堆。 

如图数组就是一个小堆

将该小堆的逻辑结构画出来就是这样的:

我们可以看到,在这棵二叉树之中的每一个父亲节点都小于它的孩子节点。 那么他就是一个小堆。 

大堆就是它的每个父亲节点都大于它的每个孩子节点

如图:

堆排序

堆排序的思想

堆排序的思想利用了大堆或小堆的结构。

我们从上面的解析可以发现。 大堆中, 第一个元素一定是整个数组中最大的那个元素;小堆中,第一个元素一定是数组中最小的那个元素。

堆排的核心就是每一趟都将堆的第一个元素和堆的最后一个元素交换位置。 然后让这个堆的元素个数减一。 同时通过向下调整算法重新建堆。 循环往复。 不断选出最大或者最小的那个数据放到堆的最后。

不知道向下调整算法可以去回顾本节:堆——c语言实现堆结构-CSDN博客

现在我们来分析一下堆的排序过程。 

我们使用小堆进行堆排:

 

第一步,将第一个元素也就是堆顶的元素和最后一个元素交换:

然后堆的大小减一:

向下调整算法重新建堆: 

 堆的第一个元素再次和堆最后一个元素交换位置:

 堆的大小减一:

 然后向下调整算法重新建堆:

然后堆的第一个元素再和堆的最后一个元素交换位置, 然后堆的大小减一, 然后向下调整算法调堆。 循环,一直到堆只剩下一个元素位置。 排好后就是这样的:​​​​​​​ 现在已经有序,同时是降序。 这时我们使用的是小堆排的。其实这里就是用大小堆控制升序降序。 小堆排的就是降序, 大堆排的就是升序。 

堆排代码

向下调整算法

我们先再来实现一次向下调整算法:


//向下调整建大堆。
void AdjustDownSort(int* a, int sz, int parent)
{

}

a是要建堆的数组, sz是数组的大小。 parent是建堆的堆顶节点 

 


//向下调整建大堆。
void AdjustDownSort(int* a, int sz, int parent)
{
	int child = parent * 2 + 1;//先假设左孩子小。 

	
}

 我们先假设左孩子比较大(注意, 我这里要建的是大堆)。


//向下调整建大堆。
void AdjustDownSort(int* a, int sz, int parent)
{
	int child = parent * 2 + 1;//先假设左孩子小。 

	while (child < sz) //控制条件是孩子不能超出整个数据。 
	{
		
        child = 2 * parent + 1;
	}
}

然后使用child指针控制循环结束。 当child指针超出整个数组的时候就不用再向下调整了。 

 


//向下调整建大堆。
void AdjustDownSort(int* a, int sz, int parent)
{
	int child = parent * 2 + 1;//先假设左孩子小。 

	while (child < sz) //控制条件是孩子不能超出整个数据。 
	{
		if (child + 1 < sz && a[child] < a[child + 1])//让child指向大的那个孩子。说明建大堆, 排升序。 
		{
			child++;
		}
		
			child = 2 * parent + 1;

		

	}
}

 因为我们是假设的左孩子比较大, 所以进入循环之后我们要比较一下左右孩子。如果右孩子更大的话就假设错误, child指针需要加加。

 


//向下调整建大堆。
void AdjustDownSort(int* a, int sz, int parent)
{
	int child = parent * 2 + 1;//先假设左孩子小。 

	while (child < sz) //控制条件是孩子不能超出整个数据。 
	{
		if (child + 1 < sz && a[child] < a[child + 1])//让child指向大的那个孩子。说明建大堆, 排升序。 
		{
			child++;
		}
		//
		if (a[child] > a[parent]) 
		{
			Swap(&a[child], &a[parent]);
			parent = child;//继续向下调整。 父亲便孩子, 孩子变成孩子的孩子。
			child = 2 * parent + 1;

		}
		else 
		{
			break;//如果父亲比小的孩子还要大, 那么这个父亲就是一个堆。 就不需要再调整建堆了。
		}
		//

	}
}

 然后在每次循环中都比较一下父亲节点和两个孩子中更小的节点。 如果孩子比父亲还要大。 就交换孩子节点和父亲节点。

如果孩子节点比父亲节点要小。 那么就说明这个堆已经建好了。 就跳出循环。

 堆排整体

一、


//堆排序
void HeapSort(int* a, int sz) 
{
		
}

 首先, 堆排的函数名以及传参。 除了快排传参基本都是传要排序的数组和数组的大小。

二、


//堆排序
void HeapSort(int* a, int sz) 
{
	int end = sz - 1;


	//先建堆, 向下调整建大堆
	for (int i = (end - 1) / 2; i >= 0; i--)//从最后一个节点的父亲开始向下调整。  一棵子树一棵子树的建成堆。最后整体成堆
	{
		AdjustDownSort(a, sz, i);//向下调整算法建大堆。
	}
	//

	while (end > 0) 
	{
		Swap(&a[0], &a[end]);//让第n个数据和堆顶最大的那个数据交换, 就能让第end个数据是最大的那个数据。 
		AdjustDownSort(a, end, 0);//第n个数据和堆顶数据交换后,前end - 1个数据只有堆顶不符合堆, 堆顶左右子树都是堆, 这时满足
		//向下调整算法。 然后向下调整。 
		end--;
	}
	
}

堆排的实现过程就是我们上面分析的过程。 首先需要一个堆。 所以先建堆。 

建完堆之后就交换堆顶和最后一个数据。 然后堆的大小减一调堆。循环往复。  

 

 

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

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

相关文章

VScode---php环境搭建

文章目录 1.下载php Dehug;php server2.下载php环境3.配置环境变量5.配置php.ini文件6.设置vscode6.测试遇到的问题 1.下载php Dehug;php server 2.下载php环境 下载地址&#xff1a;https://www.php.net/downloads.php 3.配置环境变量 C:\Users\hacker>php -v PHP 8.3.3 (…

ARM-v7 GCC 环境下的大小端转换实现

1.前言 什么是大小端转换&#xff1f;为什么叫大小端转换&#xff1f; Jonathan Swift的《格列佛游记》中记载&#xff0c;有两国因为剥鸡蛋的方式不同&#xff0c;即一国要求将熟鸡蛋的较大的一端&#xff08;大端&#xff0c;big endian&#xff09;敲碎然后剥壳&#xff0c;…

【Boost搜索引擎项目】Day1 项目介绍+去标签和数据清洗框架搭建

&#x1f308;欢迎来到C项目专栏 &#x1f64b;&#x1f3fe;‍♀️作者介绍&#xff1a;前PLA队员 目前是一名普通本科大三的软件工程专业学生 &#x1f30f;IP坐标&#xff1a;湖北武汉 &#x1f349; 目前技术栈&#xff1a;C/C、Linux系统编程、计算机网络、数据结构、Mysq…

前端从普通登录到单点登录(SSO)

随着前端登录场景的日益复杂化和技术思想的不断演进&#xff0c;前端在登录方面的知识结构变得越来越复杂。对于前端开发者来说&#xff0c;在日常工作中根据不同的登录场景提供合适的解决方案是我们的职责所在&#xff0c;本文将梳理前端登录的演变过程。 1、无状态的HTTP H…

C++编译相关学习笔记

1.编译是什么&#xff1f; 简单的说&#xff0c;就是将文本文件转化为obj对象。详细的说包含以下三个步骤&#xff1a; &#xff08;1&#xff09;预处理代码。常用的预处理语句包含#include、if、ifdef、pragma。经过这一阶段 main.cpp变为main.i 这种文件里的内容就是在原文…

【论文阅读】TensoRF: Tensorial Radiance Fields 张量辐射场

发表于ECCV2022. 论文地址&#xff1a;https://arxiv.org/abs/2203.09517 源码地址&#xff1a;https://github.com/apchenstu/TensoRF 项目地址&#xff1a;https://apchenstu.github.io/TensoRF/ 摘要 本文提出了TensoRF&#xff0c;一种建模和重建辐射场的新方法。不同于Ne…

大模型基础应用框架(ReACT\SFT\RAG)创新及零售业务落地

如何将大语言模型的强大能力融入实际业务、产生业务价值&#xff0c;是现在很多公司关注的焦点。在零售场&#xff0c;大模型应用也面临很多挑战。本文分享了京东零售技数中心推出融合Agent、SFT与RAG的大模型基础应用框架&#xff0c;帮助业务完成大模型微调、部署和应用&…

三、Distributed DataParallel分布式数据并行原理与应用

帮up宣传一下&#xff0c;优质up值得信赖&#xff01; B站UP&#xff1a;你可是处女座啊 文章目录 原理一、 DDP二、基本概念三、分布式训练中的通信 实战初始化进程组当前 进程 到底使用哪些数据&#xff1f;模型处理启动改造 loss 打印改造准确率改造数据划分训练前数据打乱…

回溯算法套路③排列型回溯+N皇后【基础算法精讲 16】

46 . 全排列 链接 : . - 力扣&#xff08;LeetCode&#xff09; 思路 : 那么怎么确定选了那个数呢? 这里设置一个used表示i选没选过 ; class Solution { public:vector<vector<int>> ans;vector<int> path;void backtrack(vector<int>nums,vect…

【小白学机器学习6】真实值,观测值,拟合值,以及数据的误差的评价:集中趋势,离散度,形状等

目录 1 世界上有哪几种值&#xff1f;只有3种值 1.1 真值/真实值/理想值/主观值&#xff08;形而上学世界里&#xff09; 1.2 实际值/现实值/观测值/样本值&#xff08;看到的/记录下来的&#xff09; 1.3 拟合值/预测值&#xff08;算出来的&#xff09; 2 对数据的各种…

【树】【异或】【深度优先】【DFS时间戳】2322. 从树中删除边的最小分数

作者推荐 【二分查找】【C算法】378. 有序矩阵中第 K 小的元素 涉及知识点 树 异或 DFS时间戳 LeetCode2322. 从树中删除边的最小分数 存在一棵无向连通树&#xff0c;树中有编号从 0 到 n - 1 的 n 个节点&#xff0c; 以及 n - 1 条边。 给你一个下标从 0 开始的整数数组…

无人机遥感在农林信息提取中的实现方法与GIS融合应用

在新一轮互联网信息技术大发展的现今&#xff0c;无人机、大数据、人工智能、物联网等新兴技术在各行各业都处于大爆发的前夜。为了将人工智能方法引入农业生产领域。首先在种植、养护等生产作业环节&#xff0c;逐步摆脱人力依赖&#xff1b;在施肥灌溉环节构建智慧节能系统&a…

1.1_2 性能指标——速率、带宽、吞吐量

文章目录 1.1_2 性能指标——速率、带宽、吞吐量&#xff08;一&#xff09;速率&#xff08;二&#xff09;带宽&#xff08;三&#xff09;吞吐量 1.1_2 性能指标——速率、带宽、吞吐量 &#xff08;一&#xff09;速率 速率即数据率或称数据传输率或比特率。 速率就是“快…

《数字图像处理(MATLAB版)》相关算法代码及其分析(2)

目录 1 将8连通边界转换为4连通边界 1.1 移除对角线转折 1.2 插入额外像素 2 将边界信息转换为二进制图像 2.1 函数定义 2.2 参数处理和验证 2.3 默认大小参数设置 2.4 根据参数调整边界位置 2.5 生成二进制图像 2.6 错误处理 3 对二值图像边界的跟踪和提取 3.1 函…

Linux运维工具-ywtool默认功能介绍

提示:工具下载链接在文章最后 目录 一.资源检查二.日志刷新三.工具升级四.linux运维工具ywtool介绍五.ywtool工具下载链接 一.资源检查 只要系统安装了ywtool工具,默认就会配置上"资源检查"的脚本资源检查脚本的执行时间:每天凌晨3点进行检查资源检查脚本的检查内容…

激活函数Swish(ICLR 2018)

paper&#xff1a;Searching for Activation Functions 背景 深度网络中激活函数的选择对训练和任务表现有显著的影响。目前&#xff0c;最成功和最广泛使用的激活函数是校正线性单元&#xff08;ReLU&#xff09;。虽然各种手工设计的ReLU替代方案被提出&#xff0c;但由于在…

C# WinForm AndtUI第三方库 Tree控件使用记录

环境搭建 1.在NuGet中搜索AndtUI并下载至C# .NetFramework WinForm项目。 2.添加Tree控件至窗体。 使用方法集合 1.添加节点、子节点 using AntdUI; private void UpdateTreeView() {Tree tvwTestnew Tree();TreeItem rootTreeItem;TreeItem subTreeItem;Dictionary<str…

代码随想录刷题笔记-Day28

1. 重新安排行程 332. 重新安排行程https://leetcode.cn/problems/reconstruct-itinerary/给你一份航线列表 tickets &#xff0c;其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。 所有这些机票都属于一个从 JFK&#xff08;肯…

centos7安装kafka、zookeeper

安装jdk 安装jdk8 安装zookeeper 在指定目录执行下载命令 我是在/newdisk/zookeeper目录下 wget https://archive.apache.org/dist/zookeeper/zookeeper-3.5.8/apache-zookeeper-3.5.8-bin.tar.gz --no-check-certificate下载好后并解压 tar -zxvf apache-zookeeper-3.5…

[译]BNF 表示法:深入了解 Python 的语法

[译]BNF 表示法&#xff1a;深入了解 Python 的语法 原文&#xff1a;《BNF Notation: Dive Deeper Into Python’s Grammar》 https://realpython.com/python-bnf-notation/ 在阅读Python文档的时候&#xff0c;你可能已经遇到过BNF(Backus–Naur form)表示法&#xff1a; 下…