树和二叉树的基本知识

news2025/3/12 14:00:25

一、树的概念及结构

1.树的概念

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

2.相关概念

节点的度:一个节点含有的子树个数称为该节点的度。如上图:根节点A的度为5

叶节点/终端节点:度为0的节点称为叶节点。如上图:B、D、G、I、K、L、M、N、O均为叶节点

分支节点/非终端节点:度不为0的节点。如上图:C、E、F、H、J为分支节点

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

3.树的表示

实际中树的表示方法有很多种,最常用的是链式存储结构的孩子兄弟表示法:

typedef int DataType;
struct Node
{
 struct Node* _firstChild; // 指向其第一个孩子结点
 struct Node* _Brother; // 指向其兄弟结点
 DataType _data; // 结点中的数据域
};

例如,上图的部分节点表示如下:

4.树的性质

①设度为i的节点个数为n_{i},则对于一颗度为m的树,其总节点个数N = n_{0}+n_{1}+...+n_{m}

②所有节点的度之和n_{1}+2n_{2}+...+mn_{m}=N-1

二、二叉树的概念

1.概念

一棵二叉树是结点的一个有限集合,该集合 :
1. 或者为空
2. 或者 由一个根节点加上两棵别称为左子树和右子树的二叉树组成
从定义可以看出,二叉树的度小于等于2,即不存在度大于2的节点。因此,任意一颗二叉树都是由以下几种情况复合而成的:
注意:二叉树≠度为2的树:二叉树的度可以为0/1/2,但度为2的树的度必须为2,即度为2的树必须存在度为2的节点,而二叉树没有此限制。

2.特殊的二叉树

满二叉树 :一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。
也就是说,如果一个二叉树的层数为K ,且结点总数是2^{k}-1,则它就是满二叉树。
完全二叉树 :完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为 K的,有n 个结点的二叉树,当且仅当其每一个结点都与深度为 K 的满二叉树中编号从 1 n 的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树

3.二叉树的性质

①若规定根节点的层数为 1 ,则一棵非空二叉树的 i 层上最多有 2^{i-1}个结点
若规定根节点的层数为 1 ,则 深度为 h 的二叉树的最大结点数是2^{h}-1
③由树的性质可知,N=n_{0}+n_{1}+n_{2}n_{1}+2n_{2}=N-1,联立上式可得n_{0}=n_{2}+1
④若规定根节点的层数为 1 ,具有 n 个结点的满二叉树的深度 h=log_{2}(n+1)

三、二叉树的存储结构

1.顺序存储

顺序存储就是使用一个数组来存储,顺序存储一般只适用于完全二叉树或近似于完全二叉树,否则会造成较大的空间浪费。现实使用中只有堆才会使用数组存储,关于堆的内容将在下篇博客【堆的实现及应用】讲解。

二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

2.链式存储

二叉树的链式存储结构是指,用链表来表示一颗二叉树,即用链来指示元素的逻辑关系。通常链表中的每个节点由三个域组成:数据域、左指针域、右指针域。其中左右指针域分别给出该节点左孩子和右孩子所在链节点的地址。这种链式结构又叫做二叉链。

typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType val;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

一颗二叉树可以分为三部分:根节点、左子树、右子树,而左右子树又都是一颗二叉树,可见二叉树的结构具有递归性,因此基于链式存储结构的二叉树算法多数也是递归的,这样代码的可读性更高、容易理解。

(1)二叉树的遍历

二叉树遍历是指按照某种特定规则依次访问二叉树的全部节点,每个节点只访问一次。

遍历是二叉树最重要的算法之一,也是其他算法的基础。

二叉树的遍历可分为四种:

①前序遍历:按照根节点、左子树、右子树的顺序遍历二叉树。如上图,遍历结果为1 2 4 6 5 3

②中序遍历:按照左子树、根节点、右子树的顺序遍历二叉树。如上图,遍历结果为4 6 2 5 1 3

③后序遍历:按照左子树、右子树、根节点的顺序遍历二叉树。如上图,遍历结果为6 4 5 2 3 1

④层序遍历:从根节点开始,自上而下、自左至右逐层访问二叉树的每个节点。如上图,遍历结果为1 2 3 4 5 6

其中,前三种遍历方式均属于递归遍历,第四种为非递归遍历。

下面以前序遍历为例演示递归遍历:

void PreOrder(BTNode* t)
{
	if (t == NULL)
	{
		printf("NULL ");
		return;
	}

	printf("%d ", t->val);
	PreOrder(t->left);
	PreOrder(t->right);
}

层序遍历需要借助队列来实现,使用队列保存每个节点的孩子节点,通过不断地入队和出队以此来实现所有节点的访问:(注:有关队列的接口函数均与上篇博客中保持一致)

void LevelOrder(BTNode* t)
{
	Queue qu;
	QueueInit(&qu);
	QueuePush(&qu, t);
	while (!QueueEmpty(&qu))
	{
		BTNode* tmp = QueueFront(&qu);
		QueuePop(&qu);
		printf("%d ", tmp->val);

		if (tmp->left != NULL)
			QueuePush(&qu, tmp->left);
		if (tmp->right != NULL)
			QueuePush(&qu, tmp->right);
	}
}

(2)二叉树的创建和销毁

已知一颗二叉树的某种递归遍历序列,如何构建出对应的二叉树?下面以前序序列为例:(注:子树为空用‘#’表示)

//创建单个节点
BTNode* SingleNode(BTDataType x)
{
	BTNode* _new = (BTNode*)malloc(sizeof(BTNode));
	if (_new == NULL)
	{
		perror("malloc error");
		exit(-1);
	}
	_new->val = x;
	_new->left = NULL;
	_new->right = NULL;

	return _new;
}

//创建二叉树
BTNode* CreateBT(char* a, int* pi)  //pi为遍历序列a的下标,开始为0
{
	if (a[*pi] == '#')
	{
		(*pi)++;
		return NULL;
	}

	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	if (root == NULL)
	{
		perror("malloc error");
		exit(-1);
	}
	root->val = a[(*pi)++]-'0';  //注意数据类型
	
	root->left = CreateBT(a, pi);
	root->right = CreateBT(a, pi);

	return root;
}

二叉树的销毁:

void BTDestroy(BTNode** pt)
{
	BTNode* t = *pt;
	if (t == NULL)
		return;

	BTDestroy(&(t->left));
	BTDestroy(&(t->right));
	free(t);
	*pt = NULL;
}

(3)其他算法

下面列举了一些有关二叉树遍历的其他算法,可以加深对递归遍历和链式结构的理解。当然,这些算法题在各大OJ平台都可以搜到。

①计算二叉树的节点个数:

int TreeNodeSize(BTNode* t)
{
	if (t == NULL)
		return 0;

	return TreeNodeSize(t->left) + TreeNodeSize(t->right) + 1;
}

②计算二叉树叶子节点的个数:

int LeafSize(BTNode* t)
{
	if (t == NULL)
		return 0;
	if (t->left == NULL && t->right == NULL)
		return 1;

	return LeafSize(t->left) + LeafSize(t->right);
}

③计算二叉树的高度:

int TreeHeight(BTNode* t)
{
	if (t == NULL)
		return 0;

	int left = TreeHeight(t->left);
	int right = TreeHeight(t->right);
	return (left > right ? left : right) + 1;
}

④计算第k层的节点个数:

int Size_k(BTNode* t,int k)
{
	if (t == NULL)
		return 0;
	if (k == 1)
		return 1;

	return Size_k(t->left, k - 1) + Size_k(t->right, k - 1);
}

⑤查找值为x的节点:

BTNode* BTFind(BTNode* t, BTDataType x)
{
	if (t == NULL)
		return NULL;
	if (t->val == x)
		return t;

	BTNode* t1 = BTFind(t->left, x);
	if (t1 != NULL)
		return t1;
	else
		return BTFind(t->right, x);
}

⑥判断两棵树是否相同:

bool isSameTree(BTNode* p, BTNode* q) 
{
	if (p == NULL && q == NULL)  //在条件判别时,p==NULL等价于!p
		return true;
	if (p == NULL || q == NULL)
		return false;

	if (p->val != q->val)
		return false;

	bool left = isSameTree(p->left, q->left);
	bool right = isSameTree(p->right, q->right);

	return left && right;
}

⑦翻转二叉树:

BTNode* invertTree(BTNode* root) 
{
	if (root == NULL)
		return NULL;

	BTNode* _root = (BTNode*)malloc(sizeof(BTNode*));
	if (_root == NULL)
	{
		perror("malloc error");
		exit(-1);
	}
	_root->val = root->val;
	_root->left = invertTree(root->right);
	_root->right = invertTree(root->left);

	return _root;
}

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

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

相关文章

上位机图像处理和嵌入式模块部署(Halcon借鉴与客户学习)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 对于很多学院派的同学来说&#xff0c;他们对市场的感觉一般是比较弱的。如果写一个软件的话&#xff0c;或者说开发一个项目的话&#xff0c;他们…

SQL-Labs靶场“11-15”关通关教程

君衍. 一、十一关 基于POST单引号字符型注入1、源码分析2、联合查询注入3、报错注入 二、十二关 基于POST双引号字符型注入1、源码分析2、联合查询注入3、报错注入 三、十三关 基于POST单引号报错注入变形1、源码分析2、报错注入 四、十四关 基于POST双引号报错注入1、源码分析…

2024阿里云云服务器ECS价格表出炉

2024年最新阿里云服务器租用费用优惠价格表&#xff0c;轻量2核2G3M带宽轻量服务器一年61元&#xff0c;折合5元1个月&#xff0c;新老用户同享99元一年服务器&#xff0c;2核4G5M服务器ECS优惠价199元一年&#xff0c;2核4G4M轻量服务器165元一年&#xff0c;2核4G服务器30元3…

项目开发日志(登录页面):1. Header组件

Header组件 样式 说明 属性 属性名含义类型是否必填默认值linkUrl图标点击后链接界面String否javascript:;(none) 属性名含义类型是否必填默认值url图片路径String是无 样式 mainColor -> 主题颜色 代码 <template><div class"header-container&qu…

定制你的【Spring Boot Starter】,加速开发效率

摘要&#xff1a; 本文将介绍如何创建一个自定义的 Spring Boot Starter&#xff0c;让您可以封装常用功能和配置&#xff0c;并在多个 Spring Boot 项目中共享和重用。 1. 简介 Spring Boot Starter 是 Spring Boot 框架中的一种特殊的依赖项&#xff0c;它用于快速启动和配置…

51_蓝桥杯_led流水灯

一 原理图分析 二 三八译码器工作原理 三八译码器&#xff1a;3个输入控制8路互斥的低电平有效输出。 C B A 输出 0 0 0 Y0 0 0 1 Y1 0 1 0 Y2 0 1 1 Y3 1 0 0 Y4 1 0 1 Y5 1 1 0 Y6 1 1 1 Y7 三 锁存器工作原理 锁存器&#xff1a;当使…

租房招聘|在线租房和招聘平台|基于Springboot的在线租房和招聘平台设计与实现(源码+数据库+文档)

在线租房和招聘平台目录 目录 基于Springboot的在线租房和招聘平台设计与实现 一、前言 二、系统功能设计 三、系统实现 1、房屋管理 2、招聘管理 3、平台资讯管理 4、平台资讯类型管理 四、数据库设计 1、实体ER图 六、论文参考 七、最新计算机毕设选题推荐 八、源…

Oracle19c PDB的简介与创建

多租用户环境&#xff08;Multitenant Environment&#xff09;&#xff0c;允许一个数据库容器&#xff08;CDB&#xff09;承载多个可插拔数据库&#xff08;PDB&#xff09;。 首先&#xff0c;毋庸置疑的是pdb只能在cdb root下创建&#xff0c;每个cdb里面都有一个pdb$seed…

自定义配置IDEA中的Java注释模板

文章目录 1.背景2.模板配置2.1.配置类模板2.2.配置方法模板2.2.1. 创建自定义模板分组2.2.2. 配置缩写、模板、触发键2.2.3. 变量配置 3.总结 1.背景 由于在公司的编码规约中关于注释的规约&#xff0c;在IDEA中的默认模板无法适配&#xff0c;所以在每次新建接口、类、方法的…

信息安全研究方向

信息安全研究方向 目前信息安全的研究包含密码学、网络安全、信息系统安全、信息内容安全、信息对抗等方向。 网络空间是所有信息系统的集合,网络安全的核心是信息安全。网络空间安全学科是研究信息的获取、存储、传输、处理等领域中信息安全保障问题的一门学科。 信息安全理…

数据分析 — Pandas 数据加载、存储和清洗

目录 一、文件读取1、常见文件读取函数2、read_csv()3、read_table()4、read_excel()5、read_json()6、read_html()7、大文件读取 二、数据保存1、csv2、excel3、json4、html5、MySQL1、连接数据库2、MySQL 存储到本地3、本地存储到 MySQL 三、数据清洗1、处理缺失值1、判断数据…

【C++初阶】第三站:类和对象(中) -- 日期计算器

目录 前言 日期类的声明.h 日期类的实现.cpp 获取某年某月的天数 全缺省的构造函数 拷贝构造函数 打印函数 日期 天数 日期 天数 日期 - 天数 日期 - 天数 前置 后置 前置 -- 后置-- 日期类中比较运算符的重载 <运算符重载 运算符重载 ! 运算符重载 …

【教3妹学编程-算法题】N 叉树的前序遍历

2哥 : 叮铃铃&#xff0c;3妹&#xff0c;准备复工了啊&#xff0c;过年干嘛呢&#xff0c;是不是逛吃逛吃&#xff0c;有没有长胖呢。 3妹&#xff1a;切&#xff0c;不想上班&#xff0c;假期能不能重来一遍啊&#xff0c;虽然在家我妈张罗着要给我相亲呢。可是在家还是很好的…

压敏电阻:浪涌保护的理想解决方案?

有关电涌保护的新法规迫使工程师寻找解决方案&#xff0c;以最小的成本损失集成此类保护&#xff0c;特别是在成本敏感的消费产品中。在汽车领域&#xff0c;电涌保护也越来越重要&#xff0c;这要归功于即使是最基本的量产车中电子含量的快速增长&#xff0c;以及公认的电源电…

MySQL简单配置GTID

前期规划 IP地址 角色 系统版本 内核 软件包名称 192.168.2.3 Mysql主服务器 CentOS Stream 9 5.14.0- 381.el9.x86_64 mysql-8.2.0-linux-glibc2.17-x86_64.tar.xz 192.168.2.4 Mysql从服务器 CentOS Stream 9 5.14.0- 381.el9.x86_64 mysql-8.2.0-linux-glibc…

C++ //练习 7.27 给你自己的Screen类添加move、set和display函数,通过执行下面的代码检验你的类是否正确。

C Primer&#xff08;第5版&#xff09; 练习 7.27 练习 7.27 给你自己的Screen类添加move、set和display函数&#xff0c;通过执行下面的代码检验你的类是否正确。 Screen myScreen(5, 5, X); myScreen.move(4, 0).set(#).display(cout); cout<<"\n"; myScr…

计算机网络——18无连接传输UDP

无连接传输UDP UDP “尽力而为的”服务&#xff0c;报文段可能 丢失送到应用进程的报文段乱序 无连接 UDP发送端和接收端之间没有握手每个UDP报文段都被独立的处理 UDP被用于 流媒体DNSSNMP 在UDP上实现可靠传输 在应用层增加可靠性应用特定的差错格式 UDP&#xff1a;用户…

综合交易模型教程---qmt实盘链接,提供源代码

综合交易模型教程---qmt实盘链接&#xff0c;提供源代码 Original L1511732 数据分析与运用 2024-02-17 00:13 贵州 目前框架实盘全部完成了&#xff0c;后面写教程&#xff0c;每一个函数怎么样使用&#xff0c;怎么样开发自己的策略 模拟盘现在登录不了我直接实盘展示 后面…

阿里云轻量应用服务器怎么样?有哪些好处?

阿里云轻量应用服务器有哪些优势&#xff1f;轻量服务器具有价格优惠、使用门槛低快速上手、灵活变配、可视化运维等优势&#xff0c;阿里云百科aliyunbaike.com整理轻量应用服务器详细优势&#xff1a; 1、价格优惠 阿里云轻量应用服务器性价比高&#xff0c;价格优惠&#x…

ubuntu制作windows的u盘启动盘

概要&#xff1a; 本篇演示在ubuntu22.04中制作windows10的u盘启动盘 一、下载woeusb 1、下载woeusb 在浏览器中输入https://github.com/woeusb/woeusb/releases访问woeusb 点击红色矩形圈出来的部分&#xff0c;下载woeusb 2、安装wimtools wimtools是woeusb的一个必须的…