树和二叉树基础概念

news2024/12/28 3:47:29

💓博主个人主页:不是笨小孩👀
⏩专栏分类:数据结构与算法👀 刷题专栏👀 C语言👀
🚚代码仓库:笨小孩的代码库👀
⏩社区:不是笨小孩👀
🌹欢迎大家三连关注,一起学习,一起进步!!💓

在这里插入图片描述

  • 树的相关概念和结构
    • 树的概念
    • 树的相关概念
    • 树的表示
  • 二叉树的概念和结构
    • 概念
    • 特殊的二叉树
    • 二叉树的存储结构
      • 顺序存储孩子和父母的下标关系
  • 堆的概念和结构
    • 堆的向上调整算法
    • 堆的向下调整算法

树的相关概念和结构

树的概念

树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因
为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
1.有一个特殊的结点,称为根结点,根节点没有前驱结点
2.除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i
3.<= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
因此,树是递归定义的。

现实中的树:
在这里插入图片描述
我们这里的结构:
在这里插入图片描述

注意:树形结构中,子树之间不能有交集,否则就不是树形结构

树的相关概念

在这里插入图片描述

节点的度:一个节点含有的子树的个数称为该节点的度; 如上图:A的为6。
叶节点或终端节点:度为0的节点称为叶节点; 如上图:B、C、H、I…等节点为叶节点。
非终端节点或分支节点:度不为0的节点; 如上图:D、E、F、G…等节点为分支节点。
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:A是B的父节点。
孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点; 如上图:B是A的孩子节点。
兄弟节点:具有相同父节点的节点互称为兄弟节点; 如上图:B、C是兄弟节点。
树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为6。
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;。
树的高度或深度:树中节点的最大层次; 如上图:树的高度为4。
堂兄弟节点:双亲在同一层的节点互为堂兄弟;如上图:H、I互为兄弟节点。
节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先。
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙。
森林:由m(m>0)棵互不相交的树的集合称为森林。

树的表示

树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既然保存值域,也要保存结点和结点之间
的关系,实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法
等。我们这里就简单的了解其中最常用的孩子兄弟表示法。

什么是孩子兄弟表示法呢?它的结构大概是这样子的

typedef int DataType;
struct Node
{
	struct Node* Child; // 第一个孩子结点
	struct Node* Brother; // 指向其下一个兄弟结点
	DataType data; // 结点中的数据域
};

它只存储第一个孩子的节点,然后在存储一个兄弟的节点,然后就通过第一个孩子,找它的兄弟,就可以找到所以孩子。
在这里插入图片描述

二叉树的概念和结构

概念

一棵二叉树是结点的一个有限集合,该集合:

  1. 或者为空
  2. 由一个根节点加上两棵别称为左子树和右子树的二叉树组成

在这里插入图片描述

  1. 二叉树不存在度大于2的结点
  2. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

特殊的二叉树

  1. 满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是 ,则它就是满二叉树。

  2. 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K 的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对 应时称之为完全二叉树。
    要注意的是满二叉树是一种特殊的完全二叉树

二叉树的存储结构

二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构。
1. 顺序存储
顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

2. 链式存储
二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链。

普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

顺序存储孩子和父母的下标关系

在这里插入图片描述
我们通过观察会发现:

左孩子=父亲×2+1;
右孩子=父亲×2+2;
父亲=(孩子-1)/2;

堆的概念和结构

如果有一个关键码的集合K = { , , ,…, },把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足: <= 且 <= ( >= 且 >= ) i = 0,1,2…,则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

在这里插入图片描述

堆的向上调整算法

我们在插入数据时,可以是用向上调整算法,来使插入的数据保持一个堆的关系。
例如我们现在给定:
int array[] = {27,15,19,18,28};

我们应该将他看成这样:
在这里插入图片描述
但是它现在不是堆,那怎么把他变成一个堆呢?(我们假设建小堆)
我们一个一个来,假设刚开始只有27,那它就是小堆,如果加个15,那它就不满足小堆的性质,我们就需要调整。

在这里插入图片描述
我们会发现向上调整算法只会影响父子之间的关系,如果父子之间不满足条件,我们就需要交换,最多需要交换到根节点就截止。
那什么是向上调整算法呢?

我们会发现我们每次向上调整时,前提它都是大堆或者小堆,也就是说,前面前面必须都是堆,插入数据时才能使用向上调整算法,并且每次都是父子之间进行的调换,当孩子是根时,就不用交换了,或者说当孩子插入后本来就满足大堆或小堆的性质,我们就不用调换,向上调整算法,就是将不满足大堆或者小堆的数据,往上面换,直到满足大堆或小堆的性质,但是前提是前面的数据已经是堆了才能够使用。

代码如下:

//向上调整算法
void AdjustUp(int* arr, int child)
{
	//计算父亲的下标
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		//判断是否满足大堆或小堆的性质(这里写的是大堆)如果孩子比父亲大,就往上面去
		if (arr[child] > arr[parent])
		{
			//Swap是个交换函数
			Swap(arr + child, arr + parent);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
		//如果本来就满足,直接跳出循环
			break;
		}
	}
}

那如何用向上调整建堆呢?
我们第一个元素就可以看成一个堆,把剩下的元素依次插入就可以。

for (int i = 1; i < sz; i++)
{
//这就和我们上面画的图想对应,依次插入,并且保证前面是堆
	AdjustUp(arr, i);
}

那么向上调整建堆的时间复杂度是多少呢?
因为时间复杂度算最坏的情况,我们这里以满二叉树为例。
在这里插入图片描述

所以向上调整算法的时间复杂度就是O(N*logN);

堆的向下调整算法

向下调整算法有一个前提:左右子树必须是一个堆,才能调整。
向下调整算法个向上调整很相似,但是条件不要一样,向下调整是堆顶的元素不满足堆的性质,需要向下调整,前提是左右子树都是堆,我们以大堆为例,我们就要选出左右子树大的那一个,和父亲比较,如果比父亲还大,就换位,如果不满足就一直换,直到换到叶子节点为止。满足就直接跳出即可。

void AdjustDown(int* arr, int sz, int parent)
{
	//假设是左孩子
	int child = 2 * parent + 1;
	while (child < sz)
	{
		//假设错误,修改
		if (child+1<sz && arr[child] < arr[child + 1])
		{
			child++;
		}
		//判断是否满足(这里写的是大堆)
		if (arr[child] > arr[parent])
		{
			Swap(arr + child, arr + parent);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}

那如何用向下调整建堆呢?
我们可以倒着来,因为叶子节点可以看成一个堆,所以我们只需要从最后一个叶子的父亲开始,向下调整就可以了;

for(int i = (sz - 1 - 1) / 2; i >= 0; i--)
{
//sz是数组的大小
	AdjustDown(arr, sz, i);
}

那么向下建堆的时间复杂度是多少呢?
我们还是以满二叉树为例。
在这里插入图片描述

所以这个的时间复杂度是O(N);

总结一下:经过我们的分析,我们可以知道向上调整建堆是不如向下调整建堆的。

今天的分享就到这里,感谢大家的支持和关注。

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

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

相关文章

Webpack 的 sass-loader 在生产模式下最小化 CSS 问题

学习webpack时候我发现一个问题&#xff1a; 将mode 改为production模式后&#xff0c;生成的css会被压缩了&#xff0c;但是我并没有引入CssMinimizerPlugin插件&#xff0c;然后我试着将optimization.minimize 设置为false&#xff0c;测试是否为webpack自带的压缩&#xff0…

微星笔记本:为京津冀、黑吉辽受灾用户提供一系列维修服务

面对近期集中在华北、东北等地出现的极端降水&#xff0c;引发洪涝和地质灾害。全国人民都众志成城、万众一心&#xff0c;在各个环节上贡献自己一份力量。台风无情、微星有爱&#xff0c;为保障您的电脑正常使用&#xff0c;京津冀、黑吉辽全区域微星线下服务中心及微星上门服…

day0808

1.单链表实现约瑟夫环 #include "joseph.h" LoopLink list_create(int m) {LoopLink L (LoopLink)malloc(sizeof(Node));if(NULLL){printf("内存创建失败\n");return 0;}LoopLink qL;for(int i1; i<m; i){LoopLink p (LoopLink)malloc(sizeof(Node));…

年轻代频繁GC ParNew导致http变慢

背景介绍 某日下午大约四点多&#xff0c;接到合作方消息&#xff0c;线上环境&#xff0c;我这边维护的某http服务突然大量超时&#xff08;对方超时时间设置为300ms&#xff09;&#xff0c;我迅速到鹰眼平台开启采样&#xff0c;发现该服务平均QPS到了120左右&#xff0c;平…

管理类联考——逻辑——论证逻辑——汇总篇——真题和典例——削弱

削弱 199-2014-10-41——割裂关系 卫计委的报告表明&#xff0c;这些年来医疗保健费的确是增加了。可见&#xff0c;我们每个人享受到的医疗条件大大改善了。 以下哪项对上述结论提出最严重的质疑? A.医疗保健费的绝大部分用在了对高危病人的高技术强化护理上。 B.在不增加费…

容器——4. Map 接口

文章目录 4.1. HashMap 和 Hashtable 的区别4.2. HashMap 和 HashSet 区别4.3. HashMap 和 TreeMap 区别4.4. HashSet 如何检查重复4.5. HashMap 的底层实现4.5.1. JDK1.8 之前4.5.2. JDK1.8 之后 4.6. HashMap 的长度为什么是 2 的幂次方4.7. HashMap 多线程操作导致死循环问题…

STL模型修复权威指南【3D打印】

设计师和工程师通常需要软件来调整、修复和最终确定 3D 打印的 3D 模型。 幸运的是&#xff0c;手动网格编程的时代早已一去不复返了。 推荐&#xff1a;用 NSDT设计器 快速搭建可编程3D场景。 如今&#xff0c;有一系列专用工具可提供自动和手动 STL 修复功能。 自动向导足以满…

zju代码题:4-6

一 分段函数算水费 #include <stdio.h>int main() {/*** 定义两个* 定义浮点型变量* y:水费* x:用水的吨数* */double x, y;printf("Enter x(x>=0):\n"

侯捷 C++ part2 兼谈对象模型笔记——2-xxx-like-classes

2 xxx-like classes 2.1 pointer-like classes 2.1.1 智能指针 设计得像指针class&#xff0c;能有更多的功能&#xff0c;包着一个普通指针指针允许的动作&#xff0c;这个类也要有&#xff0c;其中 *&#xff0c;-> 一般都要重载 template <typename T> class s…

工作中学到三个CSS伪类,直接少些几百行CSS代码~

前言 用最通俗易懂的话讲最难的知识点是我的座右铭&#xff0c;基础是进阶的前提是我的初心。分享一篇好文~ :where 基本使用 :where() CSS 伪类函数接受选择器列表作为它的参数&#xff0c;将会选择所有能被该选择器列表中任何一条规则选中的元素。 以下代码&#xff0c;文…

基于java SpringBoot和Vue零食销售网站设计

随着时代的发展&#xff0c;传统的超市购物方式已经不能满足人们的需求&#xff0c;对于顾客来说&#xff0c;排队购物和支付购物费用的问题亟待解决。对于实体超市来说&#xff0c;他们面临着网上购物的竞争压力&#xff0c;作为超市经理&#xff0c;他们要降低成本&#xff0…

全栈测试平台推荐:RunnerGo

做软件测试的同学在工作时应该都碰到过这种情况&#xff1a;接口管理、接口测试用postman、Apipost等接口管理工具&#xff0c;性能测试用jmeter、loadrunner等性能测试工具&#xff0c;接口自动化则是jmeter脚本或者python脚本配合jenkins使用。这种情况极大的降低了研发效率&…

聚观早报|网信办就人脸识别征求意见;地平线前总监入职比亚迪

【聚观365】8月9日消息 网信办就人脸识别应用征求意见地平线前总监廖杰入职比亚迪理想汽车预计三季度车辆交付量星纪魅族回应终止自研芯片业务上汽集团7月销量同比下滑21% 网信办就人脸识别应用征求意见 据网信中国微信公众号消息&#xff0c;为规范人脸识别技术应用&#xf…

自定义类型——联合

联合 1.联合体的定义 联合也是一种特殊的自定义类型。 先来看一个结构体变量&#xff1a; #include<stdio.h> #include<stdlib.h> union Un {char c;int i; }; int main() {union Un un;printf("%p\n", &un);printf("%p\n", &un.c)…

ad+硬件每日学习十个知识点(26)23.8.6 (DCDC的降压电路、升压电路、降压-升压电路,同步整流,选型考虑同步、隔离)

文章目录 1.DCDC的降压原理2.DCDC的升压原理3.DCDC的升压和降压原理4.什么是肖特基二极管造成的死区电压&#xff1f;5.MOS管有死区电压么&#xff1f;6.DCDC的同步整流&#xff08;用MOS管取代整流二极管&#xff0c;避免死区电压的影响&#xff09;7.DCDC选型——同步与非同步…

怎样学习PMP呢?

大多数人会觉得自己是工作者如果花时间去学习PMP精力上和时间上不好安排&#xff0c;其实上班族也是能学号pmp项目管理的。 首先&#xff0c;我把总结和思维导图打印出来&#xff0c;贴在镜子上&#xff0c;每天早上起来刷牙时&#xff0c;就可以过一遍这些内容。上班路上&…

《golang设计模式》第二部分·结构型模式-01-适配器模式(Adapter)

文章目录 1. 概念1.1 角色1.2 应用场景1.2 类图 2. 代码示例2.1 设计2.2 代码2.3 示例类图 1. 概念 定义一个适配器&#xff0c;帮助原本不能实现接口的类“实现”该接口 1.1 角色 目标&#xff08;Target&#xff09;&#xff1a;客户端调用的目标接口 被适配者&#xff08…

Vue3中v-model在原生元素和自定义组件上的使用

目录 前言 一、原生元素上的用法 1. 输入框(input) 2. 多行文本域(textarea) 3. 单选按钮(radio) 4. 多选框(checkbox) 5. 下拉选择框(select) 二、自定义组件上的用法 1. 定义一个名为 modelValue 的 props 属性和一个名为 update:modelValue 的事件 2.使用一个可…

岩土工程仪器多通道振弦传感器信号转换器应用于桥梁安全监测

岩土工程仪器多通道振弦传感器信号转换器应用于桥梁安全监测 桥梁作为交通运输的重要节点&#xff0c;其安全性一直备受关注。不同于其他建筑物&#xff0c;桥梁所处的环境复杂多变&#xff0c;同时&#xff0c;其所需承受的负荷也相对较大&#xff0c;这就需要对桥梁的安全进…

关于eclipse导入部署具有增删改查的项目

目录 前言&#xff1a;当我们刚刚进入公司的第一步就是去部署当前公司的项目&#xff0c;本博客就是详细介绍怎么去部署当前公司的项目。 一&#xff0c;开发工具&#xff1a; 二&#xff0c;具体步骤&#xff1a; 2.1导入公司的项目 打开eclipse开发工具 2.2配置当前的环…