news2024/12/23 13:17:15

1 树

1.1 树的基本概念

在这里插入图片描述

1.1.1 什么是树?

树是n(n >= 0)个结点的有限集。当n = 0时,称为空树。在任意一颗非空树上应该满足:

  • 有且仅有一个特定的称为的结点
  • 当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1、T2、…Tm,其中每个集合本身又是一棵树,并且称为根的子树
    在这里插入图片描述

1.1.2 树的特点

  1. 树的根结点没有前驱,除了根结点以外的所有结点有且只有一个前驱
  2. 树中所有结点可以有0个或者多个后继

1.1.3 树的基本术语

  1. 结点之间的关系:祖先结点、子孙结点、父结点、兄弟结点、孩子结点、表兄弟结点
    在这里插入图片描述
  2. 结点的度:树中一个结点的孩子个数
  3. 树的度:树中结点的最大度数
    在这里插入图片描述
  4. 结点的层次:从上往下数,根节点是第一层、它的子节点是第二层,以此类推
  5. 结点的高度:从下往上数
  6. 树的高度:总共有多少层
  7. 有序树:逻辑上看,树中结点的各子树从左至右都是有次序的,不能互换;无序树:从逻辑上看,树中结点的各子树从左至右是无次序的,可以互换
  8. 路径和路径长度。路径:这两个结点之间所经过的结点序列构成的;路径长度:路径上所经过的边的个数
  9. 森林:森林是m(m > 0)棵互不相交的树的集合。

1.2 树的性质

  1. 树中的结点数 = 所有结点数的度数之和+1
    在这里插入图片描述

  2. 度为m的树中第i层上至多有m的i-1次方个结点(i>=1)在这里插入图片描述

  3. 高度h的m叉树至多有多少结点?
    在这里插入图片描述

1.3 树的存储结构

1.3.1 顺式存储

双亲表示法:用一组连续空间来存储每个结点,同时为每个结点中增设一个伪指针(表示该结点的双亲结点的位置)

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

#define MAX_TREE_SIZE 100 // 树中最多结点数
typedef struct {// 树中结点定义
	ElemType data;// 数据元素
	int parent;// 双亲结点位置
}PTNode;
typedef struct{// 树的类型定义
	PTNode nodes[MAX_TREE_SIZE];
	int n;// 结点数
}PTree;

该存储结构的特点是比较容易得到结点的双亲结点,但是想要得到结点的孩子结点则需要遍历整个数组

1.3.2 顺式存储+链式存储

孩子表示法:每个结点的孩子结点用单链表链接在一起形成一个线性结构,而每个结点都由连续的空间存储
在这里插入图片描述代码如下:

struct CTNode {// 链式村粗的孩子结点
	int child;// 孩子结点在数组的位置
	struct CTNode *next;// 下一个结点
}
typedef struct {// 顺序存储的每个结点
	ElemType data;// 数据元素
	struct CTNode *firstChild;// 指向第一个孩子结点
}CTBox;
typedef struct {// 表示树
	CTBox nodes[MAX_TREE_SIZE];
	int n,r;// 结点数和根的位置
}CTree;

1.3.3 链式存储

孩子兄弟表示法:以二叉链表作为树的存储结构。每个结点包含三部分的内容:结点值、指向第一个孩子结点的指针、指向结点下一个兄弟结点的指针
在这里插入图片描述
代码:

typedef struct CSNode {
	ElemType data;
	struct CSNode *firdtchild,*nextsibling;// 第一个孩子以及该孩子的第一个右兄弟指针
}CSNode,*CSTree;

1.3.4 拓展 树和森林与二叉树的转换

  1. 树转森林

在这里插入图片描述森林中各个树的根被视为兄弟关系

  • 森林转树
    在这里插入图片描述

2 二叉树

2.1 什么是二叉树

二叉树就是每个结点至多有两颗子树,且左右子树有左右之分,不可以颠倒次序
其定义如下:
二叉树是n(n>=0)个结点的有限集合

  • 或者为空二叉树,即n=0
  • 或者由一个根结点和两个互不相交的被称为根的左子树和右子树组成。左子树和右子树又分别是一颗二叉树。
    在这里插入图片描述

2.2 几个特殊的二叉树

  1. 满二叉树:二叉树的每一层都是满的,也就是说一个高度为h的满二叉树,其结点有2的h次方-1个;如果按照层序编号,对于一个编号为i的结点,其左孩子的编号为2i,右结点的编号为2i+1,其双亲结点的编号为i/2的向下取整
    在这里插入图片描述

  2. 完全二叉树 :在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(h从1开始),则该层包含 1~ 2^(h-1) 个节点。
    在这里插入图片描述

  3. 二叉排序树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉排序树
    在这里插入图片描述

  4. 平衡二叉树:又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。它在满足二叉排序树的条件下,还要求任意节点的左右子树的高度差不超过1。也就是说,平衡二叉树是一棵自平衡的二叉排序树。
    在这里插入图片描述

2.3 二叉树的存储结构

2.3.1 顺序存储

1.顺式存储的方式如图:
在这里插入图片描述
2.如果父节点的数组下标是 i,那么它的左孩子就是 i * 2 + 1右孩子就是 i * 2 + 2
3.定义代码如下:

#define MaxSize 100
struct TreeNode {
	ElemType value;// 结点中的数据元素
	bool isEmpty;// 结点是否为空
}
TreeNode t[MaxSize];

2.3.2 链式存储

1.链式存储的方式如图:
在这里插入图片描述
2.代码如下:

typedef struct BiTNode {
	ElemType data;
	struct BitNode *lchild,*rchild;
}BitNode,*BiTree;
  1. 含有n个结点的二叉链表中,含有n+1个空链域。(2n-(n-1))
    解释:2n个指针域、n-1个边(代表有n-1个指针域不是空的)

2.4 二叉树的遍历

2.4.1 深度优先遍历

在这里插入图片描述

(1)先序遍历:首先访问根结点然后遍历左子树,最后遍历右子树。在遍历左、右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树。】
void preOrder(BiTree T){
	if(T) {
		visit(T);// 访问根结点
		preOrder(T->lchild);// 以此方式访问左子树
		preOrder(T->rchild);// 以此方式访问右子树
	}
}
(2)中序遍历:首先访问左子树然后访问根节点,最后访问右子树。在访问左、右子树时,仍然先访问左子树,然后根结点,最后问右子树。
void InOrder(BiTree T){
	if(T) {
		InOrder(T->lchild);// 以此方式访问左子树
		visit(T);// 访问根结点
		InOrder(T->rchild);// 以此方式访问右子树
	}
}
(3)后序遍历:首先访问左子树、其次访问右子树,最后访问根结点。在访问左、右子树时,仍然先访问左子树、再访问右子树,最后访问根结点。
void PostOrder(BiTree T){
	if(T) {
		 PostOrder(T->lchild);// 以此方式访问左子树
		 PostOrder(T->rchild);// 以此方式访问右子树
		 visit(T);// 访问根结点
	}
}
(4)例子

在这里插入图片描述

(5)由遍历序列构造二叉树
  1. 先序+中序
  2. 后序+中序
  3. 层序+中序
  4. 以上均可确立一颗二叉树

2.4.2 层次优先遍历

在这里插入图片描述算法思想

  1. 初始化一个辅助队列
  2. 根节点入队
  3. 若队列非空,则队头结点出队,访问该结点,并将其左右孩子插入队尾
  4. 重复(3)直到队列为空

代码如下:

void LevelOrder(BiTree T) {
	LinkQueue Q;
	InitQueue(Q); // 初始化辅助队列
	BiTree p;
	EnQueue(Q,T);// 根节点入队
	while(!IsEmpty(Q)) {
		DeQueue(Q,p);// 队头结点出队
		visit(p);// 访问出队结点
		if(p->lchild != NULL)
			EnQueue(Q,p->lchild);// 左孩子入队
		if(p->rchild != NULL)
			EnQueue(Q,p->rchild);// 右孩子入队
	}
}

2.5 线索二叉树

2.5.1 什么是线索二叉树

  1. 为啥要用线索二叉树?跟单向链表类似,在二叉树中想访问一个结点的双亲结点十分不容易,需要重新遍历一次二叉树才可以找到。由于一颗n个结点的二叉树有n+1个空指针域,所以就想到可不可以利用这些空指针域来储存该结点的前驱与后继呢?

以下代码是普通二叉树访问指定结点的双亲结点

// 递归中序遍历
void InOrder(BiTree T) {
	if(T!=NULL) {
		InOrder(T->left);// 左
		visit(T);// 中
		InOrder(T->right);// 右
	}
}
// 访问结点q
void visit(BiTNode *q) {
	if(q == p) // 当前访问的结点等于指定结点p时
		final = pre;// 找到p的前驱
	else
		pre = q;// pre指向当前访问的结点
}
BiTNode *p;// 目标结点
BiTNode *pre = NULL;// 当前访问结点的前驱
BiTNode *final = NULL:// 当前结点
  1. 所以引用线索二叉树的目的就是为了加快查找结点前驱和后继的速度;遍历二叉树的实质就是以一定规则将二叉树的结点排列成一个线性序列,该序列每个结点(除了首与尾)都有一个直接前驱与后继。
    下面是对线索二叉树结点的定义
typedef struct ThreadNode{
	ElemType data;// 数据元素
	struct ThreadNode *lchild,*rchild;// 左右孩子指针
	int ltag,rtag;// 左右线索标志
}

2.5.2 二叉树线索化

二叉树的线索化就是将二叉链表中的空指针改为指向前驱或后继的线索。而前驱和后继的信息只有在遍历的时候才可以得到。实质上还是遍历一下二叉树。

void InThread(ThreadTree &p,ThreadTree &pre) {
	if(p!=NULL) {
		InThread(p->lchild,pre);// 递归线索化左子树
		// 本层逻辑
		if(p->lchild == NULL) {// 该结点左孩子为空,则将其指向其父节点、线索标志位置为1
			p->lchild = pre;
			p->ltag = 1;
		}
		if(pre != NULL&&pre->rchild == NULL) {// 若该结点的前驱结点不为空且前驱节点的右孩子为空,则将其右孩子指针指向该结点、线索标志位置为1
			pre->rchild = p;
			pre->rtag = 1;
		}
		pre = p;
		InThread(p->rchild,pre);// 递归线索化右子树
	}
}

void CreateInThread(ThreadTree T) {
	ThreadTree pre = NULL;
	if(T != NULL) {
		InThread(T,pre);// 线索化
		pre->rchild = NULL;// 处理最后一个结点
		pre->rtag = 1;
	}
} 

2.5.3 在线索二叉树中寻找前驱后继

线索二叉树的结点分为两种情况,一个是线索化的结点,一个是没有线索化的结点

  1. 线索化结点:访问这类结点,直接通过其左右孩子指针就可得到其前驱后继
  2. 非线索化结点:这类结点没有被线索化的原因就是其左右指针已经用来指向其左右孩子了。所以想要得到其前驱后继,就只能通过它到底是什么方式遍历的来判断寻找它的前驱后继
  3. 以中序为例:
// 传统方法迭代找到该子树的最左下结点
ThreadNode *Firstnode(ThreadNode *p) {
	while(p->ltag == 0) p = p->lchild;// 最左下结点、不一定是叶子结点
	return p;
}
// 寻找后继
ThreadNode *Nextnode(ThreadNode *p) {
	if(p->rtag == 0) return Firstnode(p->rchild);// 若该结点的右指针没有线索化则通过传统方法迭代找到该子树的最左下结点为其后继
	else return p->rchild;// 如果线索化的,则直接返回其右指针即可
}
// 中序遍历
void Inorder(ThreadNode *T) {
	for(TreadNode *p = Firstnode(T); p != NULL; p = Nextnode(p)) {
		visit(p);
	}
}

2.6 哈夫曼树

  1. 带权路径长度
    在这里插入图片描述

    (1)结点的权:有某种现实含义的数值
    (2)结点的带权路径长度:从树的根到该结点的路径长度(经过的边数)与该结点上权值的乘积
    (3)的带权路径长度:树中所有叶子结点的带权路径长度之和

  2. 哈夫曼树的定义
    在含有n个带权叶子结点的二叉树中,其中带权路径长度最小的二叉树称为哈夫曼树,也称最优二叉树
    在这里插入图片描述以上4棵树,只有中间的两颗是哈夫曼树

  3. 哈夫曼树的构造:给定n个权值分别为w1,w2,w3,…,wn的结点,构造哈夫曼树的算法描述如下:
    (1)将这n个结点分别作为n课仅仅含一个结点的二叉树,构成森林F
    (2)构造一个新结点,从F中选取两颗根节点权值最小的二叉树作为新节点的左右子树,并且将新节点的权值置为左右子树上的根节点的权值之和
    (3)从F中删除刚才选出的两棵树、同时将新加到的树加入F中
    (4)重复步骤2和3,直到F中只剩下一棵树为止
    在这里插入图片描述

  4. 哈夫曼树的特点:
    (1)每个初始结点最终都会成为叶子结点,且权值越小的结点到根节点的路径长度越大
    (2)哈夫曼树的结点总数为2n-1
    (3)哈夫曼树没有度为1的结点
    (4)哈夫曼树不唯一,但是WPL一定相同且为最优

  5. 哈夫曼编码
    (1)固定长度编码:每个字符用相等长度的二进制位表示
    在这里插入图片描述

(2)可变长度编码:允许对不同字符用不同长度的二进制位表示
在这里插入图片描述
(3)为什么A不可以用1个二进制位去编码呢?
在这里插入图片描述

答:这样就会混淆信息了。这里引申出一个概念:前缀编码(指没有一个编码是另一个编码的前缀),这样的编码方式不会出现歧义

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

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

相关文章

webrtc学习(六)重要信令级时序图

一.四个重要信令 1.用户登录信令 SignIn 2..用户登出信令 SignOut 3..用户等待信令 wait信令是指从服务器的消息队列中获取暂存的中转消息,比如说sdp消息,对于信令服务器来说,他没有办法给用户推送消息,只能是用户推送消息给…

Leetcode151 翻转字符串中的单词

给你一个字符串 s ,请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。 注意:输入字符串 s中可能会存在前导空格、尾随空格…

元素在div中水平居中

先看一下行级元素在div中水平居中&#xff1b; <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>div demo </title> <style> body {background-color:#d0e4fe; }</style> </head><body>&…

Python基础语法入门(第二十一天)——异常处理

在Python中&#xff0c;异常处理是一种机制&#xff0c;用于捕获和处理在程序执行过程中发生的错误。 Python中的异常处理可以使用try-except语句块来实现。try语句块可能包含可能出现错误的代码段&#xff0c;而except语句块包含处理错误的代码段。当try语句块中的代码发生错…

【仿写tomcat】二、扫描java文件,获取带有@WebServlet注解的类

tomcat仿写 项目结构扫描文件servlet注解map容器servlet工具类启动类调用 项目结构 扫描文件之前当然要确定一下项目结构了&#xff0c;我这里的方案是tomcat和项目同级 项目的话就仿照我们平时使用的结构就好了&#xff0c;我们规定所有的静态资源文件都在webApp目录下存放…

数学建模之“灰色预测”模型

灰色系统分析法在建模中的应用 1、CUMCM2003A SARS的传播问题 2、CUMCM2005A长江水质的评价和预测CUMCM2006A出版社的资源配置 3、CUMCM2006B艾滋病疗法的评价及疗效的预测问题 4、CUMCM2007A 中国人口增长预测 灰色系统的应用范畴大致分为以下几方面: (1&#xff09;灰色关…

go 协程并发数控制

错误的写法&#xff1a; 这里的<-ch 是为了从channel 中读取 数据&#xff0c;为了不使channel通道被写满&#xff0c;阻塞 go 协程数的创建。但是请注意&#xff0c;go workForDraw(v, &wg) 是不阻塞后续的<-ch 执行的&#xff0c;所以就一直go workForDraw(v, &…

react使用antd的table组件,实现点击弹窗显示对应列的内容

特别提醒&#xff1a;不能在table的columns的render里面设置弹窗组件渲染&#xff0c;因为这会导致弹窗显示的始终是最后一行的内容&#xff0c;因为这样渲染的结果是每一行都会重新渲染一遍这个弹窗并且会给传递一个content的值&#xff0c;渲染到最后一行的时候&#xff0c;就…

水库工程标准化管理运行方案

水库工程标准化管理是指在水库建设、运行和维护过程中&#xff0c;按照一定的标准和规范进行管理&#xff0c;以确保水库工程的安全、高效运行。标准化管理可以提高水库工程的质量、节约资源、保护环境&#xff0c;并最大程度地减少事故风险。以下是水库工程标准化管理的几个重…

【Redis】Redis 的主从同步

【Redis】Redis 的主从同步 很多企业都没有使用 Redis 的集群&#xff0c;但是至少都做了主从。有了主从&#xff0c;当主节点(Master) 挂掉的时候&#xff0c;运维让从节点 (Slave) 过来接管&#xff0c;服务就可以继续&#xff0c;否则主节点需要经过数据恢复和重启的过程&a…

2.SpringMvc中Model、ModelMap和ModelAndView使用详解

1.前言 最近SSM框架开发web项目&#xff0c;用得比较火热。spring-MVC肯定用过&#xff0c;在请求处理方法可出现和返回的参数类型中&#xff0c;最重要就是Model和ModelAndView了&#xff0c;对于MVC框架&#xff0c;控制器Controller执行业务逻辑&#xff0c;用于产生模型数据…

使用JMeter创建数据库测试

好吧&#xff01;我一直觉得我不聪明&#xff0c;所以&#xff0c;我用最详细&#xff0c;最明了的方式来书写这个文章。我相信&#xff0c;我能明白的&#xff0c;你们一定能明白。 我的环境&#xff1a;MySQL&#xff1a;mysql-essential-5.1.51-win32 jdbc驱动&#xff1a;…

python有绿色版软件吗,python绿色版运行程序

大家好&#xff0c;给大家分享一下python有绿色版软件吗&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 简介 本文介绍使用 conda 命令&#xff08;来自 Anaconda 软件包&#xff09;创建绿色便携版 python 的方法。此版本不但有 Python 的…

【C++初阶】引用计数和写时拷贝是什么?用来干嘛的?

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

jeecgboot-vue3 查询区 label 文字居左实现

以系统管理中的系统角色界面为例 操作步骤 1. 通过路由或者工具找到当前代码所在的文件 src/views/system/role/index.vue 2. 找到 useListPage 调用&#xff0c;fromConfig 对象加入 labelWidth 和 rowProps 属性 formConfig: {labelWidth: 65, // 设置所有的label宽rowPr…

badgerdb里面的事务

事务的ACID A 原子性&#xff08;Atomicity&#xff09; 多步骤操作&#xff0c;只能是两种状态&#xff0c;要么所有的步骤都成功执行&#xff0c;要么所有的步骤都不执行&#xff0c;举例说明就是小明向小红转账30元的场景&#xff0c;拆分成两个步骤&#xff0c;步骤1&#…

13、Redis与Mysql数据双写一致性

Redis与Mysql数据双写一致性 1、 复习&#xff0b;面试题 先动Mysql&#xff0c;再动Redis&#xff0c;两害相衡取其轻&#xff0c;避免Redis业务key突然消失&#xff0c;多线程请求集火打满mysql 动&#xff0c;写操作&#xff0c;先更新数据库&#xff0c;在删除缓存。回写的…

面试时如何回答接口测试怎么进行

一、什么是接口测试 接口测试顾名思义就是对测试系统组件间接口的一种测试&#xff0c;接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系等。 …

基础课-不等式

1.记录 最小公倍数是最大公约数的倍数 2.均值不等式 和定积大 积定和小- 机顶盒小

83-基于stm32单片机DHT11温湿度监测报警系统Proteus仿真+源码

资料编号&#xff1a;083 一&#xff1a;功能介绍&#xff1a; 1、采用stm32单片机OLED显示屏DHT11温湿度蜂鸣器&#xff0c;制作一个温湿度采集&#xff0c;OLED显示相关数据&#xff0c; 2、通过按键设置温度上限、湿度上限&#xff1b; 3、当采集温度大于设置温度&#xff0…