【数据结构】堆的创建

2023-09-13 19:33:44

在这里插入图片描述

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤
📃个人主页 阿然成长日记 👈点击可跳转
📆 个人专栏: 🔹数据结构与算法🔹C语言进阶
🚩 不能则学,不知则问,耻于问人,决无长进
🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍

前言:

在上一篇博客中,主要讲到了关于堆的各种操作。那么本篇博客将会讲讲我们通过堆可以实现的一些作用-----如堆排序

一、基于大堆的上下调整

上一篇博客中的上下调整,都是以调成小堆为目标。那怎样才能实现调成大堆呢?🌸

1.向上调整

(1)解决措施:

只需要修改比较符>;改为a[parent]<a[child],即可

(2)代码实现

//向上调整
void AdjustUp(HPDataType* a, int child)
{
	//传入数组,child为孩子节点下标
	int parent = (child - 1) / 2;
	//当一直交换到根,停止
	while (child>0)
	{
		if (a[parent] < a[child])
		{
			Swap(&a[parent], &a[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			return;
	}
}


(3)测试

输入数组:int a[] = { 2,4,5,3,1,9 };
在这里插入图片描述

2.向下调整

(1)解决措施:

只需要修改比较符 <改为child + 1 < n && a[child + 1] > a[child],
因为建大堆,需要找大的那个进行交换。

(2)代码实现

//向下调整
void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	//一直交换到数的最后,也就是数组的最后一个位置
	while (parent<n)
	{
		if (child + 1 < n && a[child + 1] >a[child])
		{
			child++;
		}
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			// 继续往下调整
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			return;
		}
	}
}

3.总结

-大堆小堆
向上调整parent>childparent<child
向下调整比较两个孩子,选择的进行比较交换选择的进行比较交换

二、创建堆(小堆)

两种方法建堆均以建立小堆为目标。无论是创建小堆还是创建大堆,思路都一样,通过修改Adjust方法即可

建堆【方法一】使用向上调整

创建堆的思路可以通过向上调整,也可通过向下调整。这里讲通过向上调整建立堆.<从上到下>

1.思路

传入参数
a:数组,n:是数组元素个数
1.为p->a开辟n个空间;
2.利用memcpy函数,把数组a复制到p->a中
3.在使用基于小堆的AdjustUp调整,从根逐步向下延伸,其实也就类似于插入调整;
在这里插入图片描述
在这里插入图片描述

2.代码实现

//建立大堆
void HeapInitArray(HP* p, int* a, int n)
{
	//a:数组,n:是数组元素个数
	assert(p);
	assert(a);

	p->a = (HPDataType*)malloc(sizeof(HPDataType) * n);
	if (p->a == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	p->size = n;
	p->capacity = n;
	//把传入数组a复制到p->a中
	memcpy(p->a, a, sizeof(HPDataType) * n);

	// 向上调整,调整成一个小堆
	for (int i = 1; i < n; i++)
	{
		AdjustUp(p->a, i);
	}
}

建堆【方法二】使用向下调整

这里通过向下调整建立堆.<从下到上>

1.思路:

1.从倒数第一个非叶子节点开始向下调整,因为叶子节点没有左右子树。
2.根据基于小堆的Adjust方法,比较交换。
3.层层向上,下层可以保证是堆。从而可保证向下调整的进行。
所以,我们说这种调整方式是从下到上的。
步骤图
在这里插入图片描述
在这里插入图片描述

三、堆排序

🌸排升序

口诀:排升序,建大堆

意思是:想要将数组的顺序变成一个升序的,那么可以建立一个大堆存在数组中,在对堆进行调整。即可将数组变成一个升序数组。

1.思路:

首先建立大堆;
1.堆顶与最后一个节点交换,由于是大堆,堆顶是最大值。交换后,就选出了最大值并将其放到数组的组后位置
2.并将堆的长度减1(数组长度减1)。
3.在对剩下的堆进行基于大堆的向下调整从而将第二大的数调整到了堆顶。此步骤时间复杂度:O(logN)
4.最后,这个原本存储大堆的数组,就变成了一个从小到大的升序数组

2.代码实现:

//排升序
void HeapSortASC(int* a, int n)
{
	//建立大堆
	for (int i = 1; i < n; i++)
	{
		AdjustUp(a, i);
	}
	int end = n - 1;
	while (end > 0)
	{
		swap(&a[0], &a[end]);
		//每次调整从根0到end,end每次会减1。
		AdjustDown(a, end, 0);
		end--;
	}
}

3.时间复杂度分析

一次AdjustUp调整的时间复杂度是O(logN)
一共执行n-1次,所以,时间复杂度一共是O(N*logN)。

🌱排降序

口诀:排降序,建小堆

1.思路:

首先建立小堆;
1.堆顶与最后一个节点交换,由于是小堆,堆顶是最小值。交换后,就选出了最小值并将其放到数组的组后位置,
2.并将堆的长度减1(数组长度减1)。
3.在对剩下的堆进行基于小堆的向下调整从而将第二小的数调整到了堆顶。此步骤时间复杂度:O(logN)
4.最后,这个原本存储小堆的数组,就变成了一个从小到大的降序数组

2.代码实现:

修改AdjustUp(a, i);和AdjustDown(a, end, 0);为调小堆

void HeapSortDES(int* a, int n)
{
	//建立小堆
	for (int i = 1; i < n; i++)
	{
		AdjustUp(a, i);
	}
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		//每次调整从根0到end,end每次会减1。
		AdjustDown(a, end, 0);
		--end;
	}
}

3.时间复杂度分析

一次AdjustUp调整的时间复杂度是O(logN)
一共执行n-1次,所以,时间复杂度一共是O(N*logN)。

更多推荐

C++之互斥锁、读写锁、互斥量、 信号量、原子锁机制总结(二百二十五)

简介:CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀人生格言:人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.更多原创,欢迎关注:Android系统攻城狮1.前言本篇目的:C++之

Python——urllib库

urllib是一个用来处理网络请求的python内置库。一.基本使用二.一个类型和6个方法2.1一个类型urllib的request库中urlopen方法返回的类型:<class'http.client.HTTPResponse'>。为了与之后request库做区别。2.26个方法read()方法:获得响应正文,按字节

基于Java+vue前后端分离学习交流论坛设计实现(源码+lw+部署文档+讲解等)

博主介绍:✌全网粉丝30W+,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌🍅文末获取源码联系🍅👇🏻精彩专栏推荐订阅👇🏻不然下次找不到哟2022-2024年最全的计算机软件毕业设计选题

rv1126之isp黑电平(BLC)校准!

前言:大家好,今天我们继续来讲解isp第二期内容,这期内容主要分三个部分:1、tunning的工作流程2、利用RKISP2.x_Tuner来创建tunning工程,并连接上rv1126开发板进行抓图3、BLC(黑电平校准)的原理和校准方法以及实战那对于RKISP2.x_Tuner的工具使用,这个在第一期的内容里面有详细

从零开始在树莓派上搭建WordPress博客网站并实现公网访问

文章目录序幕概述1.安装PHP2.安装MySQL数据库3.安装Wordpress4.设置您的WordPress数据库设置MySQL/MariaDB创建WordPress数据库5.WordPressconfiguration6.将WordPress站点发布到公网安装相对URL插件修改config.php配置7.支持好友链

php程序设计的基本原则

单一职责原则(SRP):一个类应该只有一个原因引起变化,即一个类应该只负责一项职责。classUser{private$name;private$email;publicfunction__construct($name,$email){$this->name=$name;$this->email=$email;}pu

HTML5 游戏开发实战 | 俄罗斯方块

俄罗斯方块是一款风靡全球的电视游戏机和掌上游戏机游戏,它曾经造成的轰动与造成的经济价值可以说是游戏史上的一件大事。这款游戏看似简单但却变化无穷,游戏过程仅需要玩家将不断下落的各种形状的方块移动、翻转,如果某一行被方块充满了,那就将这一行消掉;而当窗口中无法再容纳下落的方块时,就宣告游戏结束。可见俄罗斯方块的需求如下。(

AI+游戏线下沙龙活动暨COC上海城市开发者社区8月活动

引言近年来,随着人工智能技术的不断发展和游戏开发技术的不断更新,越来越多的游戏公司开始将人工智能技术应用于游戏领域,以提高开发效率、降低成本,实现游戏玩家更好的游戏体验。为了探讨AI+游戏的技术实践经验,近日在亚马逊会议中心举办了一场以AI+游戏为主题的技术研讨会。在AI+游戏的技术实践研讨会上,与会者们分享了一些关于

云游戏下,会带来哪些技术变革

云游戏前言元宇宙是什么?云游戏的福利云游戏包括哪些技术前言大家好,在这里给大家介绍一个新名词----云游戏。可能有一些小伙伴了解过一些,也有一些小伙伴可能没有了解过,那这里就带大家了解一下元宇宙里的云游戏。2023年,如果说到什么最火🔥,什么最流行,那肯定是非元宇宙莫属了。自从2021年来,元宇宙就如同那雨后春笋一样

方案:数智化视频AI技术为智慧防汛筑基,构建防汛“数字堤坝”

一、背景分析在过去的几年中,全球气候变化导致许多城市在雨季面临严重的洪涝灾害。这些灾害不仅对人们的生命安全和财产造成威胁,也影响了城市的正常运转。传统的防汛手段主要依赖人力监控和应急指挥,但存在响应速度慢、处理效率低等问题。因此,我们需要一种智能、高效的解决方案来提高防汛效率和降低洪涝灾害的影响。随着新一代信息技术的普

【JavaSE专栏49】Java集合类LinkedList解析,链表和顺序表有什么不同?

作者主页:Designer小郑作者简介:3年JAVA全栈开发经验,专注JAVA技术、系统定制、远程指导,致力于企业数字化转型,CSDN学院、蓝桥云课认证讲师。主打方向:Vue、SpringBoot、微信小程序本文讲解了Java中集合类LinkedList的语法、使用说明和应用场景,并给出了样例代码。目录一、什么是Lin

热文推荐