堆排序详细理解

news2025/1/19 20:43:26

目录

一、前备知识

二、建堆

2.2.1 向上调整算法建堆

2.2.2 向下调整算法建堆

三、排序

3.1 常见问题 

3.2 思路

3.3 源码


一、前备知识

详细图解请点击:二叉树的顺序实现-堆-CSDN博客

本文只附上向上/向下调整算法的源码

//交换
void Swap(int* p, int* q)
{
	int tmp = *p;
	*p = *q;
	*q = tmp;
}
//向下调整算法
void AdjustDown(int* a, int n, int parent)
{
	//左孩子的下标
	int child = parent * 2 + 1;
	while (child<n)
	{
		//找到两个孩子中较小的孩子-假设法
		if (child + 1 < n && a[child + 1] < a[child])
		{
			child++;
		}
		if (a[parent] > a[child])
		{
			Swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
//向上调整算法
void AdjustUp(int* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

二、建堆

堆排序堆排序,先有堆才能排序,所以排序的第一步是要将一个一般的数组建成堆。

注:由于建大堆还是小堆仅仅取决于自定的大小于号,本文下述建堆都以小堆为例

2.2.1 向上调整算法建堆

思路:

  1. 单一的一个结点可以看成一个堆
  2. 后续的所有结点都可以看作是插入结点

所以只需要循环插入所有后续结点即可

void BuildHeap1(int* a, int n)
{
	//把根节点看作是堆,剩下的结点看作插入结点,开始依次插入
	for (int i = 1; i < n; i++)
	{
		AdjustUp(a, i);
	}
}

2.2.2 向下调整算法建堆

错误思路:

向下调整算法要求左右子树必须为大/小堆,所以从根节点开始结点开始建堆的做法是错误的

正确思路:

上文说:单一的一个结点可以看成一个堆所以从最后一个叶子节点的父节点开始向下调整,不断循环所有父节点,就可以保证他的左右子树都是堆。

void BuildHeap2(int* a, int n)
{
	//从最后一个叶子结点的父结点开始调
	for (int i = ((n - 1) - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, n, i);
	}
}

三、排序

3.1 常见问题 

  • 为什么建堆后依然还要排序?

        大堆/小堆的定义注定了堆仅仅能保证父节点大于孩子结点,无法保证孩子结点按照大于/小于的次序严格排列!!!

  • 升序建小堆,降序建大堆的思路是否可行?
  1. 升序建小堆:首先对 n 个数建小堆,选出最小的数,接着对剩下的 n-1 个数建小堆,选出第二小的数,不断重复上述过程。若用向上调整算法可行但时间复杂度太高,若使用向下调整算法时,对n-1个调整就会发现:原先的孩子父亲关系全乱,不可行。
  2. 降序建大堆:首先对 n 个数建小堆,选出最小的数,接着对剩下的 n-1 个数建大堆,选出第二大的数,不断重复上述过程。使用向下调整算法时,对n-1个调整就会发现:原先的孩子父亲关系全乱,不可行。

3.2 思路

  1. 本质上是堆删除的思路。利用堆的特性,无论是大堆还是小堆,根节点的值一定是最大/小的数。这样每进行一次调整,就会选择出最小/大,次小/大......便可以实现排序。
  2. 为了防止出现父子关系乱序的问题,将每次找到的最值放在堆的末位置,对前n-1个元素进行向下调整,便可以完美解决排序问题
  3. 由此可以总结:升序建大堆,降序建小堆

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

1. 把无序数组构建成二叉堆。

2. 循环删除堆顶元素,移到数组尾部,调节堆产生新的堆顶。

3.3 源码

//降序建小堆
void HeapSortDown(int* a, int n)
{
	//建小堆
	for (int i = ((n - 1) - 1) / 2; i >= 0; i--)
    {
	    AdjustDown(a, n, i);
    }
	//排序
	int end = n - 1;        //定位数组最后一个位置
	while (end > 0)
	{
		Swap(&a[0], &a[end]);	// 将堆顶元素和堆中最后一个元素交换,把最大的数(堆顶)放到最后
		AdjustDown(a, end, 0);
		end--;					// 调整前n-1个元素
	}
}

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

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

相关文章

数据安全之翼:天空卫士在汽车数据安全领域的卓越领航

近期&#xff0c;中国汽车网络安全与数据安全产业的积极倡导者谈思实验室发布首份《汽车网络与数据安全行业全景图》&#xff0c;天空卫士入选&#xff0c;并且位列榜首。 天空卫士在汽车数据安全领域有丰富的实践经验&#xff0c;曾为多家汽车行业用户提供数据安全产品与服务&…

Docker 私有仓库部署和管理

目录 一、案例一 概述 二、案例一 前置知识点 2.1、什么是 Docker Compose 2.2、什么是 Consul 三、案例一 使用 docker Compose 搭建 Consul 集群环境 3.1、案例实验环境 3.2、案例需求 四、案例实施 4.1、Docker 网络通信 1&#xff09;端口映射 2&#xf…

【Python】 如何将Python脚本打包为独立可执行文件

基本原理 在Python开发中&#xff0c;我们经常会遇到需要将脚本打包成可执行文件的情况。这样做的好处是&#xff0c;用户可以在没有安装Python环境的情况下运行程序&#xff0c;同时&#xff0c;程序的依赖项也会被打包进去&#xff0c;避免了因为环境不一致导致的问题。 Py…

C++ 混合运算的类型转换

一 混合运算和隐式转换 257 整型2 浮点5 行吗&#xff1f;成吗&#xff1f;中不中&#xff1f; C 中允许相关的数据类型进行混合运算。 相关类型。 尽管在程序中的数据类型不同&#xff0c;但逻辑上进行这种运算是合理的相关类型在混合运算时会自动进行类型转换&#xff0c;再…

Wpf 使用 Prism 实战开发Day30

登录界面设计 一.准备登录界面图片素材&#xff08;透明背景图片&#xff09; 1.把准备好的图片放在Images 文件夹下面&#xff0c;格式分别是.png和.ico 2.选中 login.png图片鼠标右键&#xff0c;选择属性。生成的操作选择>资源 3.MyTodo 应用程序右键&#xff0c;属性&a…

【简单介绍下Milvus,什么是Milvus?】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

YZW900规格书

title: “深圳市沃进科技有限公司” 深圳市沃进科技有限公司 TOP视图 特性 异地组网&#xff0c;远程访问有线/无线备份单模双卡备份5G转有线&#xff0c;5G转WIFI2.4G5.8G双频WIFI三网口&#xff0c;WAN/LAN可切换软硬件看门狗智能防掉线云平台、客户端远程管理安装支架安装铝…

JVM哪些区域可能出现内存溢出,哪些地方需要GC?

GC顾名思义也就是垃圾回收&#xff0c;有人的地方就有江湖&#xff0c;那有数据的地方也理应有垃圾回收&#xff0c;所以思考一下&#xff0c;沿着之前提到过的JVM内存分区&#xff0c;堆&#xff0c;栈&#xff0c;程序计数器&#xff0c;方法区 堆、栈、方法区…

使用 Apache Commons Exec 自动化脚本执行实现 MySQL 数据库备份

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

为何懂行的人都在选海信Mini LED?

今年的618大促比往年来得要更早一些。纵览各电商平台的电视产品&#xff0c;能发现Mini LED电视的出镜率很高&#xff0c;成了各大品牌的主推产品。 对于什么样的Mini LED更值得买&#xff0c;各品牌都有自己的说辞。因为缺乏科学系统的选购标准&#xff0c;消费者容易在各方说…

Python零基础-下【详细】

接上篇继续&#xff1a; Python零基础-中【详细】-CSDN博客 目录 十七、网络编程 1、初识socket &#xff08;1&#xff09;socket理解 &#xff08;2&#xff09;图解socket &#xff08;3&#xff09;戏说socket &#xff08;4&#xff09;网络服务 &#xff08;5&a…

Docker安装Redis(云服务器)

准备&#xff1a; 在云服务器中开启6370端口号 docker run -d --name redis -p 6379:6379 redis 这条命令使用docker运行一个名为"redis"的容器&#xff0c;映射容器的6379端口到主机的6379端口&#xff0c;并且使用redis镜像来运行容器。REDIS是一个开源的内存数据…

18.Redis之哨兵

1.哨兵机制的介绍 通过自动化的手段,来解决主节点挂了的问题~~ 哨兵机制, 是通过独立的 进程 来体现的.和之前 redis-server 是不同的进程!! redis-sentine| 不负责存储数据,只是对其他的 redis-server 进程起到监控的效果~~ 通常哨兵节点,也会搞一个集合~~(多个哨兵节点构成的…

TQSDRPI开发板教程:实现LWIP自环

项目资源分享 链接&#xff1a;https://pan.baidu.com/s/1QckFYSwua-Fpxk3tewledQ 提取码&#xff1a;bewt 打开vivado2019.1创建工程 下一步 设置工程名称与地址。勾选reate…选项&#xff0c;会创建一个新的文件夹&#xff0c;项目保存在其中&#xff0c;文件夹名称与工程名…

伦敦金1手指的是什么?

就算没有进行过伦敦金投资&#xff0c;甚至是没有做过任何金融产品投资的朋友&#xff0c;相信也听过别人做交易决定&#xff0c;他们都是1手两手那样头买入。有些朋友就好奇了&#xff0c;这伦敦金1手指的是什么意思&#xff1f;下面我们就来讨论一下。 首先&#xff0c;如果我…

云计算与 openstack

文章目录 一、 虚拟化二、云计算2.1 IT系统架构的发展2.2 云计算2.3 云计算的服务类型 三、Openstack3.1 OpenStack核心组件 一、 虚拟化 虚拟化使得在一台物理的服务器上可以跑多台虚拟机&#xff0c;虚拟机共享物理机的 CPU、内存、IO 硬件资源&#xff0c;但逻辑上虚拟机之…

【论文导读】Grid Graph Reduction for Efficient Shortest Pathfinding(2023 Access)

Grid Graph Reduction for Efficient Shortest Pathfinding 作者&#xff1a;CHAN-YOUNG KIM AND SANGHOON SULL 文章提出了一种“基于模式识别的网格阻塞”&#xff08; Pattern-Based Blocking on grid graphs&#xff0c;PBGG&#xff09;的预处理方法&#xff0c;以加快最…

【康耐视国产案例】智能AI相机联合OSARO为Zenni眼镜实现订单履约自动化

在电商潮流下&#xff0c;Zenni眼镜作为全球领先的在线眼镜零售商&#xff0c;每年销售超过600万副眼镜&#xff0c;却面临着一个独特而复杂的问题——需要通过扫描眼镜盒内的条形码来处理订单。传统手动处理已经到达流程瓶颈&#xff0c;急需一种更加自动化、可扩展的方法。为…

小数第n位【蓝桥杯】

小数第n位 模拟 思路&#xff1a;arr数组用来记录已经出现过的a&#xff0c;在循环时及时退出。易知题目的3位即a%a后的第n-1,n,n1位。该代码非常巧妙&#xff0c;num记录3位的输出状况。 #include<iostream> #include<map> using namespace std; typedef long l…

Python实现定时任务的三种方案——schedule、APScheduler、Celery

schedule schedule是一个轻量级的Python库&#xff0c;用于定期执行任务&#xff0c;即定时任务调度。它提供了一种简单直观的方式来自定义任务执行的时间规则&#xff0c;而无需复杂的线程或进程管理知识。schedule适用于那些需要在后台定期执行某些功能的Python应用程序&…