【数据结构】筛选法建堆

news2024/10/7 8:25:32

💞💞 前言

hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹
在这里插入图片描述

💥个人主页:大耳朵土土垚的博客
💥 所属专栏:数据结构
这里将会不定期更新有关数据结构的内容,希望大家多多点赞关注收藏💖💖

目录

  • 💞💞 前言
  • 1.建堆的方法
  • 2.堆向上调整算法建堆及时间复杂度
    • ✨堆向上调整算法
    • ✨使用堆向上调整算法建堆
    • ✨时间复杂度计算
  • 3.筛选法建堆及时间复杂度
    • ✨堆向下调整算法
    • ✨使用堆向下调整算法建堆
    • ✨时间复杂度计算
  • 4.结语

1.建堆的方法

给你一个顺序表或数组(一串数据),通常来说建堆有两种方法一种堆向上调整算法,一种堆向下调整算法建堆也就是筛选法建堆。

筛选法建堆是一种快速建堆的方法,它是在堆排序算法中使用的。这种方法的基本思想是通过不断筛选节点,如果建大堆就将大的节点向上筛选,小的节点向下筛选,小堆就反之,最终得到一个有序的堆。

下面将以将数组int arr[] = {1,8,9,5,3,2}建成一个小堆为例介绍两种方法建堆

2.堆向上调整算法建堆及时间复杂度

✨堆向上调整算法

//向上调整算法
void AdjustUp( int* arr,int child)
{
	//找到双亲节点
	int parent = (child - 1) / 2;
	//向上调整
	while (child > 0)
	{
	//如果父节点大于子节点就交换
		if (arr[parent] > arr[child])
		{
			Swap(&arr[parent], &arr[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			break;

	}
}

因为我们建的是小堆所以父节点肯定是要小于子节点的,所以当遇到父节点大于孩子节点就交换,相应的如果建的是大堆那么父节点小于孩子节点就交换

✨使用堆向上调整算法建堆

堆向上调整算法调整的是最后一个元素,前面的元素必须是一个堆,所以我们在使用堆向上调整算法时可以从一串数的第二个元素开始调整,它前面只有一个元素(一个元素就可以看成一个堆),调整完之后前面两个元素就是一个堆了,再从第三个元素开始调整,依此类推直到最后一个元素

图解如下:
int arr[] = {1,8,9,5,3,2}可以表示为:

在这里插入图片描述

①第一个数据1可以看成一个堆,从第二个节点8开始向上调整,发现1<8,不需要交换:

在这里插入图片描述

②前面两个数据1和8已经构成小堆,从第三个元素开始向上调整,发现1<9不需要交换:

在这里插入图片描述

③前面三个数据已经构成小堆,从第四个数据5开始向上调整,发现5<8交换,交换后1<5,不需要交换:

在这里插入图片描述

④前面四个数据构成小堆,从第五个数据3开始向上调整建堆,发现3<5交换,1>3不交换:

在这里插入图片描述

⑤前面五个数据构成小堆,从第六个数据2开始往上调整建堆,发现2<9交换,1<2不交换:

在这里插入图片描述

建好堆之后入下图:

在这里插入图片描述

代码如下:

int main()
{
	int arr[] = { 1,8,9,5,3,2};
	//使用堆向上调整算法建堆,需要从第二个节点开始依次往上调整
	for (int i = 1; i < sizeof(arr)/sizeof(int); i++)
	{
		AdjustUp(arr, i);
	}
	//打印数组
	for (int i = 0; i < sizeof(arr)/sizeof(int); i++)
	{
		cout << arr[i] << " ";
	}
	return 0;
}

结果如下:
在这里插入图片描述

✨时间复杂度计算

在这里插入图片描述

由上图可知,堆向上调整法建堆的时间复杂度是NlogN

logN是以2为底的

3.筛选法建堆及时间复杂度

筛选法建堆需要利用我们的向下调整算法:

✨堆向下调整算法


//堆向下调整算法
void AdjustDown(int* arr,int n, int parent)
{
	//找到较小的孩子节点
	int child = parent * 2 + 1;

	//向下调整
	while (child < n)
	{
		//找到较小的孩子节点
		if (child + 1 < n && arr[child] > arr[child + 1])
		{
			child++;
		}
		//如果父节点大于孩子节点就交换
		if (arr[child] < arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			parent = child;
			child = child * 2 + 1;
		}
		else
			break;

	}
}

✨使用堆向下调整算法建堆

具体步骤如下:

  1. 从完全二叉树中的最后一个非叶子节点开始,将其视为根节点。
  2. 从根节点开始,依次向下进行筛选,将当前节点与其左右子节点进行比较,将最大值上移。
  3. 完成一次筛选后,将当前节点的上一个节点作为新的根节点,再次进行筛选。
  4. 依次类推,直到所有节点都进行过一次筛选,最终得到一个有序的堆。

这里同样要注意,堆向下调整时,其节点左右子树必须是堆,我们从最后一个非叶子节点开始调整是因为其左右子树只有一个数据,可以看成堆

以int arr[] = {1,8,9,5,3,2}为例,图解如下:

在这里插入图片描述

①从最后一个非叶子节点9开始往下调整,发现9>2交换:

在这里插入图片描述

②再从上一个节点8开始往下调整,先找到较小的孩子节点3,发现8>3交换:

在这里插入图片描述

③再从上一个节点1开始往下调整,找到较小的子节点2,发现1<2不交换:

在这里插入图片描述
小堆就建好了:

在这里插入图片描述
代码如下:

int main()
{
	int arr[] = { 1,8,9,5,3,2 };
	//使用堆向下调整算法建堆,需要从最后一个非叶子节点开始依次往下调整
	int size = (sizeof(arr) / sizeof(int) - 2) / 2;//找到最后一个非叶子节点下标
	for (int i = size; i >=0; i--)
	{
		AdjustDown(arr, sizeof(arr) / sizeof(int),i);
	}
	//打印数组
	for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
	{
		cout << arr[i] << " ";
	}
	return 0;
}

结果如下:

在这里插入图片描述

我们发现堆向下调整需要多传一个参数数据个数n,这是因为向下调整时,最坏的情况下会一直向下调整到最后一个节点,此时要控制下标不能越界,所以要传数据个数来防止越界,而前面的向上调整最坏的情况下,会调整到根节点,只需要其下标不小于0就不会越界,所以不需要传参数n

✨时间复杂度计算

在这里插入图片描述
由上图可知,堆向下调整法建堆的时间复杂度是N

4.结语

由上述时间复杂度的分析可知,我们最好选用筛选法也就是堆向下调整算法建堆,以上就是今天所有的内容啦~ 完结撒花~ 🥳🎉🎉

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

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

相关文章

Golang | Leetcode Golang题解之第134题加油站

题目&#xff1a; 题解&#xff1a; func canCompleteCircuit(gas []int, cost []int) int {for i, n : 0, len(gas); i < n; {sumOfGas, sumOfCost, cnt : 0, 0, 0for cnt < n {j : (i cnt) % nsumOfGas gas[j]sumOfCost cost[j]if sumOfCost > sumOfGas {break}…

Android 14.0 Settings主页面去掉自定义您的设备等菜单相关功能

1.前言 在14.0的系统rom产品定制化开发中,在系统Settings主页面的主菜单中,在测试某些功能的时候,比如开启护眼模式和改变系统密度会在主菜单第一项的网络菜单头部增加 自定义您的设备和设置护眼模式时间安排 等等相关的设置模块 这对于菜单布局显示相当不美观,所以根据系…

TSR,FSR,DLSS超级分辨率的原理分析

先了解一些时域抗锯齿的方法&#xff1a; TAA&#xff1a; 抖动 TAA 的主要原理是跨帧计算多个子像素样本&#xff0c;然后将它们组合成一个最终像素。最简单的方案是在像素内生成随机样本&#xff0c;但有更好的方法来生成固定序列的样本。选择一个好的序列以避免聚集非常重…

MacOS 安装C语言版TensorFlow

文章目录 安装C语言版TensorFlow解压归档环境变量c_api.hC语言示例 安装C语言版TensorFlow 官方文档&#xff1a;https://tensorflow.google.cn/install/lang_c?hlzh-cnTensorFlow 提供了一个 C API&#xff0c;该 API 可用于为其他语言构建绑定。该 API 在 c_api.h 中定义&a…

我有点想用JDK17了

大家好呀&#xff0c;我是summo&#xff0c;JDK版本升级的非常快&#xff0c;现在已经到JDK20了。JDK版本虽多&#xff0c;但应用最广泛的还得是JDK8&#xff0c;正所谓“他发任他发&#xff0c;我用Java8”。 其实我也不太想升级JDK版本&#xff0c;感觉投入高&#xff0c;收…

【TB作品】 51单片机8x8点阵显示滚动汉字仿真

功能 题目5基于51单片机LED8x8点阵显示 流水灯 直接滚动显示HELLO 直接滚动显示老师好 代码 void main( void ) {/** 移位后&#xff0c;右边的是第一个595&#xff0c;接收0X02&#xff0c;显示出0X02* 移位后&#xff0c;左边的是第2个595&#xff0c;接收0Xfe&#xff0c…

C++结合OpenCV进行图像处理与分类

⭐️我叫忆_恒心&#xff0c;一名喜欢书写博客的在读研究生&#x1f468;‍&#x1f393;。 如果觉得本文能帮到您&#xff0c;麻烦点个赞&#x1f44d;呗&#xff01; 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧&#xff0c;喜欢的小伙伴给个三…

人工智能任务5-高级算法工程师需要学习哪些课程与掌握哪些能力

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能的任务5-高级算法工程师需要学习哪些课程&#xff0c;需要掌握哪些能力。高级算法工程师需要掌握的算法模型有&#xff1a;人脸检测模型MTCNN&#xff0c;人脸识别方法Siamese network、center loss、softm…

在VSCode中安装python

引言 Python 是一种广泛使用的高级编程语言&#xff0c;因其易学、易用、强大而受到欢迎。它由 Guido van Rossum 于 1991 年首次发布&#xff0c;并以简洁的语法和丰富的库生态系统而著称。 以下是 Python 的一些关键特点和优势&#xff1a; 关键特点 易于学习和使用&#x…

AWS的EC2之间ping不通,服务之间不通,怎么办

AWS启动的两个EC2实例&#xff0c;互相访问不了 修改安全组规则&#xff0c;添加ICMP 流量的入站规则 参考&#xff1a;AWS的EC2之间ping不通,服务之间不通,怎么办_aws ec2同一个区域的服务器-CSDN博客

选择排序-Java版本

选择排序 算法的思想&#xff1a;java模拟 算法的思想&#xff1a; 每遍历一次就找一个最小的数 *外层 一共遍历 length-1次 总遍历次数符合等差数列 时间复杂度为O(n^2)内部查找 并 返回 数值 和 下标 java模拟 public static void selectSort(int[] arr) {for(int i 0;i<…

MyBatis拦截器使用方法

前言 MyBatis拦截器可以做的工作&#xff1a;SQL修改&#xff0c;分页操作&#xff0c;数据过滤&#xff0c;SQL执行时间性能监控等。 1. 基础介绍 1.1. 核心对象 从MyBatis代码实现的角度来看&#xff0c;MyBatis的主要的核心部件有以下几个&#xff1a; Configuration&am…

InfiniGate自研网关实现思路七

25.网关Nginx负载模型配置 通过模拟多个HTTP服务配置到 Nginx 做负载均衡&#xff0c;以学习API网关负载的配置和使用 API 网关是用于支撑分布式 RPC 接口协议转换提供 HTTP 调用的一套服务&#xff0c;那么 API 网关系统就需要可横向扩展来满足系统的吞吐量诉求。所以这里需…

如何根据业务需求,轻松挑选SSL证书?

在当今数字化时代&#xff0c;网站的安全性愈发受到重视。SSL证书作为网站安全的“守门员”&#xff0c;不仅能保护用户数据不被窃取&#xff0c;还能提升网站的信任度。但面对市场上琳琅满目的SSL证书产品&#xff0c;如何根据业务需求挑选合适的证书呢&#xff1f;今天&#…

今日份动态规划学习

主要只搞了一个这道题&#xff0c;有点摸鱼了今天晚上&#xff0c;也是来小看一下这道题吧01背包完全背包 P1941 [NOIP2014 提高组] 飞扬的小鸟 题意&#xff1a; 这题是说&#xff0c;给我们一个游戏界面&#xff0c;界面的长度为n&#xff08;水平距离&#xff09;&#x…

Java | Leetcode Java题解之第134题加油站

题目&#xff1a; 题解&#xff1a; class Solution {public int canCompleteCircuit(int[] gas, int[] cost) {int n gas.length;int i 0;while (i < n) {int sumOfGas 0, sumOfCost 0;int cnt 0;while (cnt < n) {int j (i cnt) % n;sumOfGas gas[j];sumOfCos…

【活动】程序员的核心职业素养:技术与人文并重的探索之旅

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 程序员的核心职业素养&#xff1a;技术与人文并重的探索之旅1. 持续学习与技术精…

Python Lambda函数的应用实例教程

在Python编程中&#xff0c;lambda函数是一种简洁且强大的工具&#xff0c;用于创建小型匿名函数。它们在需要快速定义简单函数时特别有用。本文将详细介绍lambda函数的语法及其多种应用实例&#xff0c;帮助读者更好地理解和使用lambda函数。 一、lambda函数的基本概念 1.1 什…

多个p标签一行展示,溢出隐藏

一开始&#xff0c;我是让div包裹多个p标签&#xff0c;并让div“flex”布局&#xff0c;且单行溢出隐藏&#xff0c;可是发现当父元素或当前元素有flex时&#xff0c;text-overflow: ellipsis;是不生效的 大多数解决办法都是&#xff0c;不要flex&#xff0c;或者给div下的每个…

计算机网络 期末复习(谢希仁版本)第6章

DNS采用UDP。 DHCP 给运行服务器软件、且位置固定的计算机指派一个永久地址&#xff0c;给运行客户端软件的计算机分配一个临时地址