二叉树介绍及堆

news2024/11/19 7:25:41

文章目录

概念及结构

二叉树

概念及结构

特殊的二叉树

完全二叉树

满二叉树

性质

储存

顺序存储

链式储存

概念及结构

小堆

大堆

建堆

向上调整建堆

向下调整建堆

TOPK问题

法一:

法二:


概念及结构

     树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树。

  • 树的第一个结点被称为根结点
  • 除根结点外,其余结点被分成M(M>0)个互不相交的集合T1、T2.....、Tm,其中每一个集合Ti(1<=i<=m)又是一颗结构与树类似的子树。所以树是用递归定义的。

0c5edabadecc481d86e09af44bbe8f33.png   

 下面是树的常见相关概念

7a50dc4d67ed4395bbd62bcf3934c304.jpg

  • 度:一个结点含有的子树的个数称为该结点的度。如上图:A的度为6。
  • 叶结点:度为0的节点称为叶结点。如上图:P是叶结点。
  • 子结点:一个结点含有的子树的根结点称为该结点的子结点。如上图:B是A的子结点。
  • 父结点:若一个结点含有子结点,则这个结点称为父结点。如上图:A是B的父结点。
  • 树的高度或深度:树中节点的最大层次。如上图:该树的高度是4。

     注意:子树之间不能有交集(F只能有一个父结点)。

7e5511d35f1c4271afdfa30c2fbe7684.png

二叉树

概念及结构

     二叉树是一种特殊的树,其特点是每个结点最多只能有棵子树,且有左右之分。所以二叉树是有序树

9d77e0ea9a4249cd946a93c8c119107a.png

     一般称左边的树为左子树,右边为右子树最上边的结点是根结点。

c93aa9b0f0204989b79f4f1a376d3953.png

特殊的二叉树

完全二叉树

     假设该树有h层,则前h-1层的结点数都达到了最大,第h层结点连续集中在左边。

aaf756e7f864416d921ff0e4d407ccea.png

满二叉树

     如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。

     满二叉树是属于完全二叉树的。

c5dc249ad1704e55b684de6af05c73e8.png

性质

     1.若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)个结点。

     2. 若规定根结点的层数为1,则深度为h的二叉树的最大结点数是 2^h-1

     3. 对任何一棵二叉树, 如果度为0其叶结点个数为N0 , 度为2的分支结点个数为N2 ,则有N0 = N2+1

     4. 若规定根结点的层数为1,具有n个结点的满二叉树的深度,h= log2(n+1)。(log以2为底,n+1为对数)

     5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有结点从0开始编号,则对于下标i的结点有:

       (1)若i>0,i位置结点的父结点序号:(i-1)/2;若i=0,i为根结点无父结点。

       (2)若2*i+1<n,左孩子序号:2i+1,若2*i+1>=n否则无左孩子。

       (3)若2*i+2<n,右孩子序号:2i+2,若2*i+2>=n否则无右孩子。

储存

顺序存储

     顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。

     在物理上是数组,在逻辑上是二叉树。

b65175cb8a5b4059939239958657531d.png

链式储存

     链式结构存储就是用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。每个结点通常有三个域,数据域和左右指针域。

1e9fe6384d2a473b816acaac061d99cb.png

概念及结构

     堆是一种特殊的树形数据结构,通常表现为一棵完全二叉树,是用二叉树的顺序存储方式来存储元素的。

     堆分为小堆和大堆

小堆

     父结点小于子结点,但是父结点下面的两个子结点没大小区分。

90434b351ba54f5fbbdd3a7e9487de84.png

大堆

     父结点大于子结点,但是父结点下面的两个子结点没大小区分。

39670b21154e45ce9b4379c882f2c69d.jpg

建堆

     以下均为建小堆

向上调整建堆

     适用于一边插入一边建堆的情况。

     找到该孩子的父结点(利用上面性质5),在让父结点与它进行比较如果小于它则退出,如果大于则交换位置,重复上述操作直至循环结束或跳出循环。

void AdjustUp(int* arr, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (arr[child] < arr[parent])//将<改为>即建大堆
		{
			Swap(&arr[child], &arr[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			break;
	}
}

     注:Swap是交换位置函数。

void Swap(int* p1, int* p2)
{
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}

向下调整建堆

     适用于对根节点进行调整。

     找到它的两孩子中小的那个,在让这个小的孩子与它进行比较如果孩子大于它则退出,如果小于则交换位置,重复上述操作直至循环结束或跳出循环。

void AdjustDown(int* arr, int n, int parent)
{
	int child = (parent * 2) + 1;
	while (child < n)
	{
		if (child + 1 < n && arr[child + 1] < arr[child])//child + 1 < n防止非法访问,将后面的<改为>即建大堆
        {
			child++;
        }
		if (arr[parent] > arr[child])//将<改为>即建大堆
		{
			Swap(&arr[parent], &arr[child]);
			parent = child;
			child = (parent * 2) + 1;
		}
		else
			break;
	}
}
//以上两个大小号均需要更改才能是建大堆

TOPK问题

     TOPK问题:即求数据结合中前K个最大的元素或者最小的元素。一般来说数据量比较大。

     如果有一个数组,数组里有N个数据,我们要找最大的前K个数据,要怎么做呢?

     找最大的前K个元素建大堆。

     找最小的前K个元素建小堆。

法一:

     先建一个大堆,然后让第一个结点的数据与最后一个结点交换,拿出最后的那个结点,然后再让根结点向下调整。重复上述操作K次。

void Heapsort(int* a, int n)
{
	int k = 0;
	scanf("%d", &k);
	for (int i = 0; i < n; i++)
	{
		AdjustUp(a, i);
	}
	while (k--)
	{
		Swap(&a[n - 1], &a[0]);
		AdjustDown(a, n - 1, 0);
		n--;
	}
}

     搞完后,数值大的数据都在数组的后面。我在这里没有拿出来。

法二:

     先建一个K个数据的小堆,然后让后面的N-K个数据跟该小堆的根结点进行比较,如果大于则进行交换,然后向下调整。最后拿出该堆即可。

void Heapsort(int* a, int n)
{
	int k = 0;
	scanf("%d", &k);
	for (int i = (k - 2) / 2; i >= 0; i--)
	{
		AdjustDown(a, k, i);
	}

	for (int i = k; i < n; i++)
	{
		if (a[i] > a[0])
		{
			Swap(&a[i], &a[0]);
			AdjustDown(a, k, 0);
		}
	}
}

     大家应该注意到了哈,这次建堆的方式有点不一样,这是先找到树的最后一个根结点(画四角星的是树的最后一个根结点)

ddab68e75d384c83aea977311d641089.jpg

然后向下调整建堆,然后遍历最后一个根结点之前的结点建堆。使用这种方式建堆会更方便时间复杂度为N,使用上面建堆方式时间复杂度是NlogN。

     总的来说法二要比法一要更优,因为当数据比较多时法一把所有的数据建堆就有点浪费时间了。

     在下篇中我会介绍二叉树的链式结构实现。

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

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

相关文章

小白跟做江科大32单片机之LED流水灯

1.复制下面地址新建的工程&#xff0c;改名为3-2 LED流水灯 小白跟做江科大32单片机之LED闪烁-CSDN博客https://blog.csdn.net/weixin_58051657/article/details/139295351?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%2213929…

每天学点小知识:Windows终端Powershell美化

前言 本章的旨在教会你美化自己的终端&#xff0c;powershell需要以管理员运行 经过我的测试&#xff0c;不同的电脑可能会有不同的报错&#xff0c;具体操作根据官方为主https://ohmyposh.dev/docs 效果展示 Oh My Posh&#xff1a;提供美观的 PowerShell 提示符主题 1.安装…

【UE5.1 角色练习】08-物体抬升、抛出技能 - part2

目录 前言 效果 步骤 一、让物体缓慢的飞向手掌 二、向着鼠标方向发射物体 前言 在上一篇&#xff08;【UE5.1 角色练习】08-物体抬升、抛出技能 - part1&#xff09;的基础上继续完成角色将物体吸向手掌&#xff0c;然后通过鼠标点击的方向来发射物体的功能。 效果 步骤…

linux开发之设备树四、设备树中断节点

中断节点 这里是由原厂的BSP工程师写的一部分 在CPU的外部有一个GIC控制器&#xff0c;外设会连接在GIC控制器上 设备树是对硬件进行描述的&#xff0c;所以设备树会对CPU进行描述&#xff0c;也要对GIC 控制器进行描述&#xff0c;这部分的代码由原厂的BSP工程师进行编写&…

【蓝桥杯嵌入式】 第六届国赛

目录 题目 配置 注意事项 代码 - 默写大师 EEPROM读写函数 LED驱动函数 ADC采集 上电初始化 LCD 按键 PWM互补输出 全部代码 hardware.c hardware.h control.c control.h main.c 题目 配置 注意事项 复制LCD的工程&#xff0c;先配置资源 --- 勾选完选项一…

ARM-V9 RME(Realm Management Extension)系统架构之系统能力的执行隔离

安全之安全(security)博客目录导读 目录 一、执行隔离 1、安全状态 2、安全模型 本博客探讨 RME 所需的系统能力&#xff0c;以保证 Arm CCA 对于 Realms 的安全性和隔离特性。 一、执行隔离 1、安全状态 RME 系统支持以下安全状态&#xff1a; 非安全 (Non-secure)安全…

台灯护眼是真的吗?警惕这六大问题!

在当今社会&#xff0c;随着电子设备的普及和长时间的用眼&#xff0c;大多数人面临着严重的视觉疲劳问题。长时间盯着屏幕或学习&#xff0c;眼睛需要不断调节焦距&#xff0c;导致眼睛肌肉疲劳&#xff0c;进而引发视力下降。这种现象在年轻一代甚至青少年中尤为普遍&#xf…

Sourcetree安装教程及使用

1 Sourcetree介绍 Sourcetree是一款免费的Git图形化客户端&#xff0c;它由Atlassian开发&#xff0c;提供了跨平台的支持&#xff0c;可运行在Windows和Mac操作系统上。Sourcetree可以让开发者更方便地使用Git来管理代码&#xff0c;不需要在命令行中输入复杂的Git命令&#x…

10W QPS高并发,如何防止重复下单?

小北说在前面 10wqps高并发&#xff0c;如何防止重复提交/支付订单&#xff1f; 10wqps高并发&#xff0c;如何防止重复下单&#xff1f; 10wqps高并发&#xff0c;如何防止重复支付&#xff1f; 10wqps高并发&#xff0c;如何解决重复操作问题&#xff1f; 最近有小伙伴在面试…

Go开发Prometheus客户端实战步骤

1、项目背景 在当前的IT运维环境中&#xff0c;我们的业务系统日益复杂&#xff0c;特别是针对特定的业务逻辑和定制化需求&#xff0c;传统的通用监控工具往往难以覆盖所有的监控场景。例如&#xff0c;考虑到一个复杂的电商平台&#xff0c;除了基础的服务器性能、网络状况等…

JavaScript-内存分配

内存空间 内存分为栈和堆 栈&#xff1a;由操作系统自动释放存放的变量值和函数值等。简单数据类型存放在栈中 栈会由低到高先入后出 堆&#xff1a;存储引用类型 &#xff08;对象&#xff09; 对象会先将数据存放在堆里面&#xff0c;堆的地址放在栈里面

HTB-SherlocksDFIR

Sherlocks 中关于 DFIR 的一些内容&#xff0c;按照时间线整理&#xff0c;尚未完成&#xff0c;持续更新​ Brutus 和上一次做的 Recollection 机器一样&#xff0c;主要学习一下相关的知识&#xff0c;练习一下。按照机器描述&#xff0c;在学习完成后将熟悉 auth.log 和 wtm…

自建视频托管平台:MediaCMS

目录 1 MediaCMS简介1.1 介绍1.2 特性1.3 应用场景 2 安装配置2.1 安装1、安装2、汉化 2.2 一些常见配置 3 简单使用3.1 上传3.2 下载3.3 添加标题或者字幕3.4 通过Tag/Category实现视频/文件分类添加 Tag给任一资源分类 1 MediaCMS简介 1.1 介绍 MediaCMS是一个现代的&#…

2.10 mysql设置远程访问权限

2.10 mysql设置远程访问权限 目录1. 管理员运行mysql命令窗口2. 使用 root 用户重新登录 MySQL3. 修改用户权限4. 修改mysql安装目录下的my.ini 目录 说明&#xff1a; Mysql8.0 设置远程访问权限 一、Mysql8.0 设置远程访问权限 1. 管理员运行mysql命令窗口 2. 使用 root 用…

Java break细节(标签)

Java break细节(标签)continue也可以使用标签 break是用来跳出循环的。 当有多重循环时&#xff0c;可以配合标签来使用&#xff0c;决定跳出那一重循环。 尽量不要使用标签 1、不代标签时&#xff0c;默认跳出 break 所在的那重循环&#xff1a; 可见在 i 3 时&#xff0…

前端调用exe程序配置

前置条件 访问端安装好需要调用的exe程序 1、新建reg文件 先新建一个txt文件&#xff0c;重命名为xx.reg 点击是&#xff0c;确认更改 2、编写注册表内容 右键点击文件&#xff0c;用记事本打开&#xff0c;输入以下内容 将下面的${exeName}修改为自定义的程序名&#x…

react使用react-quill富文本编辑器自定义上传图片,添加handlers后编辑器不显示问题

Quill介绍 Quill 是一款 API 驱动、功能强大的现代富文本编辑器。它具有易于拓展、各平台表现一致性等优点。Quill 官方 1.0 版本于 2016 年 9 月发布&#xff0c;目前在 Github 上有41.8k Star。 官网地址&#xff1a;Quill - Your powerful rich text editor github仓库地…

剪画小程序:视频伪原创怎么制作?视频伪原创的几种制作方法分享!

什么是视频伪原创&#xff1f; 视频伪原创是指对已有的视频内容进行一定程度的修改和处理&#xff0c;使其在形式或部分细节上与原始视频有所不同&#xff0c;但保留了核心内容或主题。 视频伪原创包括以下一些常见操作&#xff1a; 剪辑重组&#xff1a;对原始视频进行剪辑…

整合SSM框架笔记

整合SSM框架笔记 Spring5 Spring MVC MyBatis Druid MySQL Thymeleaf 感谢尚硅谷课程&#xff1a;B站课程 前言 单Spring框架时&#xff0c;是Java工程。 Spring与Spring MVC可以共用一个配置文件&#xff0c;也可以不共用一个&#xff0c;推荐不共用一个。 Spring与Sp…

map优化多个if

原代码如下&#xff0c;多个按钮的点击操作&#xff0c;其中val是操作的按钮的标志 const operationConst {INSTALLAPP: installApp,STOPAPP: stopApp,HOME: home,CLEAR: clear...... } function moreOperation(val, list) {selectedList list && list.length 0 ?…