数据结构——树与二叉树基础

——本节内容为Bilibili王道考研《数据结构》P38~P42视频内容笔记。

目录

一、树的基本概念

1.相关术语

2.结点之间的关系描述

3.结点、树的属性描述

4.有序树和无序树

5.树和森林

二、树的性质

1.结点数=总度数+1(总度数+根结点)。

2.度为m的树、m叉树

3.树的最多结点

 4.树的最少结点

5.m叉树最小高度

三、二叉树的定义和基本术语

1.基本概念

2.二叉树的五种状态

3.特殊二叉树

四、二叉树的性质

1.二叉树性质1

2.二叉树性质2

3.二叉树性质3

4.完全二叉树性质1

5.完全二叉树性质2

五、二叉树的存储结构

1.顺序存储

2.链式存储


一、树的基本概念

1.相关术语

(1)空树:结点数为0的数。

(2)非空树:

        ①有且只有一个根结点;

        ②没有后继的结点称为“叶子结点”(终端结点);

        ③有后继的结点称为“分支结点”(非终端结点);

        ④除了根结点以外,任何一个结点都有且仅有一个前驱;

        ⑤每个结点可以有0个或多个后继。

(3)子树:每个结点可分为多个互不相交的有限集合,其中每个集合本身又是一棵树,并且称为该结点的子树(结点A有三棵子树,结点B有两棵子树,结点F没有子树)。

(4)树是一种递归定义的数据结构。


2.结点之间的关系描述

 (1)祖先结点:从自身开始向上追溯直到根结点,途径的所有结点都称为祖先结点(图示“你”的祖先结点有:“父亲”、“爷爷”)。

(2)子孙节点:由自身所产生的所有结点都称为子孙节点(图示除了“爷爷”以外所有的结点都称为“爷爷”的子孙结点)。

(3)双亲结点(父结点):自身的前驱称为双亲结点(图示“你”的双亲结点为“父亲”)。

(4)孩子结点:自身的所有后继都称为孩子结点(图示“父亲”的孩子结点为“你”和“F”)。

(5)兄弟结点:自身的前驱所产生的其他结点称为兄弟结点(图示“F”为“你”的兄弟结点)。

(6)堂兄弟结点:除了“兄弟结点”,处于一层中的所有结点都称为堂兄弟结点(图示“G”、“H”、“I”、“J”都称为“你”的堂兄弟结点)。

(7)路径:两个结点之间的路径只能是从上往下的单向方向。

(8)路径长度:两个结点的路径长度指它们之间的边的个数。


3.结点、树的属性描述

(1)结点的层次(深度):即该结点处于这棵树从上往下数的第几层(图示“E”结点的层次为3)。

(2)结点的高度:即该结点处于这棵树从下往上数的第几层(图示“E”结点的高度为2)。

(3)树的高度(深度):即该树一共有多少层(图示的树的高度为4)。

(4)结点的度:即该结点的“孩子结点”的个数(图示“B”结点的度为2,“D”结点的度为3)。

        ①非叶子结点的度>0;

        ②叶子结点的度=0。

(5)树的度:即各结点的度的最大值(图示的树的度为3)。


4.有序树和无序树

(1)有序树:从逻辑上看,树中结点的各子树从左至右是有次序的,不能互换。

(2)无序树:从逻辑上看,树中结点的各子树从左至右是无次序的,可以互换。 

(3)具体要看你用树存什么,是否需要用结点的左右位置来反应某些逻辑关系。


5.树和森林

(1)森林:森林是m(m>=0)棵互不相交的树的集合。

 (2)m可以为0,即代表空森林。


二、树的性质

1.结点数=总度数+1(总度数+根结点)。


2.度为m的树、m叉树

(1)树的度:各结点的度的最大值;所以度为m的树应:

①任意结点的度<=m(最多有m个孩子);

②至少有一个结点度=m;

③一定是非空树,至少有m+1个结点。

(2)m叉树:每个结点最多只能有m个孩子的树;所以m叉树应:

①任意结点的度<=m(最多有m个孩子);

②允许所有结点的度都<m;

③可以是空树;

 


3.树的最多结点

(1)度为m的树第i层至多有{m_{}}^{i-1}个结点(i>=1);

(2)m叉树第i层至多有{m_{}}^{i-1}个结点(i>=1)。

 (3)高度为h的m叉树最多有\frac{​{m_{}}^{h}-1}{m-1}个结点。

(等比数列求和:m^{0}+m^{1}+m^{2}+......+m^{h-1}=\frac{​{m_{}}^{h}-1}{m-1}


 4.树的最少结点

(1)高度为h的m叉树至少有h个结点。

 (2)高度为h、度为m的树至少有h+m-1个结点。


5.m叉树最小高度

(1)具有n个结点的m叉树的最小高度为\left \lceil log_{m}^{}(n(m-1)+1)\textrm{} \right \rceil

(2)高度最小的情况:所有结点都有m个孩子(即往宽了长)。

(3)分析过程如下: 


三、二叉树的定义和基本术语

1.基本概念

(1)二叉树是n(n>=0)个结点的有限集合:

        ①空二叉树,即n=0;

        ②由一个根结点和两个互不相交的被称为根的左子树和右子树组成,左子树和右子树又分别是一棵二叉树。

 

 (2)特点:

        ①每个结点至多只有两棵子树;

        ②左右子树不能颠倒(二叉树是有序树)。


2.二叉树的五种状态

 


3.特殊二叉树

(1)满二叉树

①定义:一棵高度为h,且含有{2_{}}^{h}-1个结点的二叉树。

②图像:

 ③特点:

Ⅰ只有最后一层有叶子结点;

Ⅱ不存在度为1的结点(要么为2,要么为0);

Ⅲ按层序从1开始编号,结点i的左孩子为2i,右孩子为2i+1;结点i的父节点为\left \lfloor \frac{i}{2} \right \rfloor(如果有的话)。

(2)完全二叉树

①定义:当且仅当其每个结点都与高度为h的满二叉树中编号为1~n的结点一一对应时,称为完全二叉树。

②图像:

 ③通俗解释:就是把一个满二叉树里较大的连续编号删掉,比如上面图示中删掉了最后一层中后三个结点,其余编号和满二叉树的编号相对应。

④特点:

Ⅰ只有最后两层可能有叶子结点;

Ⅱ最多只有一个度为1的结点;

Ⅲ按层序从1开始编号,结点i的左孩子为2i,右孩子为2i+1;结点i的父节点为\left \lfloor \frac{i}{2} \right \rfloor(如果有的话);

 Ⅳi\leq \left \lfloor \frac{n}{2} \right \rfloor为分支结点,i> \left \lfloor \frac{n}{2} \right \rfloor为叶子结点;

Ⅴ如果一个完全二叉树的某个结点只有一个孩子的话,那么这个孩子一定是左孩子。

(3)二叉排序树

①定义:一棵二叉树或者是空二叉树,或者是具有如下性质的二叉树:

Ⅰ左子树上所有结点的关键字均小于根结点的关键字;

Ⅱ右子树上所有结点的关键字均大于根结点的关键字。

②左子树和右子树又各是一棵二叉排序树。

③图像:

 

(4)平衡二叉树

①定义:树上任一结点的左子树和右子树的深度之差不超过1。

②图像:

 ③平衡二叉树有更高的搜索效率。


四、二叉树的性质

1.二叉树性质1

(1)设非空二叉树中度为0、1、2的结点的个数分别为n0、n1、n2,则n0=n2+1(叶子结点比二分支结点多一个);算法如下:

(2)假设树中结点总数为n,则:

        ①n=n0+n1+n2;

        ②n=n1+2n2+1(树的结点数=总度数+1);

        ③用②-①得到:n0=n2+1。


2.二叉树性质2

二叉树第i层最多有2^{i-1}个结点(i>=1)。


3.二叉树性质3

高度为h的二叉树最多有2^{h}-1个结点(满二叉树)。


4.完全二叉树性质1

(1)具有n个(n>0)结点的完全二叉树的高度h为\left \lceil log_{2}^{}(n+1)\textrm{} \right \rceil\left \lfloor log_{2}^{}n\textrm{} \right \rfloor+1。 算法如下:

 (2)第n个结点所在层次为\left \lceil log_{2}^{}(n+1)\textrm{} \right \rceil\left \lfloor log_{2}^{}n\textrm{} \right \rfloor+1


5.完全二叉树性质2

(1)对于完全二叉树,可以由总的结点数n推出度为0、1、2的结点个数为n0、n1、n2。

(2)算法:

①完全二叉树最多只有一个度为1的结点,即n1=0或1;

②由n0=n2+1得n0+n2=2n2+1一定是一个奇数;

③若完全二叉树有2k(偶数)个结点,则必有n1=1,n0=k,n2=k-1;

④若完全二叉树有2k-1(奇数)个结点,则必有n1=0,n0=k,n2=k-1。


五、二叉树的存储结构

1.顺序存储

(1)代码实现:

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

TreeNode t[MaxSize];

(2)定义长度为MaxSize的数组t,按照从上到下、从左到右的顺序依次存储完全二叉树中的各个结点,如下图所示:

①图示,让第一个位置t[0]空缺,可保证数组下标和结点编号一致。

②几个重要的基本操作:

        Ⅰi结点的左孩子:2i;

        Ⅱi结点的右孩子:2i+1;

        Ⅲi结点的父结点:\left \lfloor \frac{i}{2} \right \rfloor

        Ⅳi结点所在的层次: \left \lceil log_{2}^{}(n+1)\textrm{} \right \rceil\left \lfloor log_{2}^{}n\textrm{} \right \rfloor+1

③若完全二叉树中共有n个结点,则:

        Ⅰ判断i是否有左孩子:2i<=n?

        Ⅱ判断i是否有右孩子:2i+1<=n?

        Ⅲ判断i是否是叶子/分支结点:i> \left \lfloor \frac{n}{2} \right \rfloor?

(3)如果不是完全二叉树,依然按层序将各个结点顺序存储:

        ①情况如图:

         ②这些结点的编号将无法反应结点之间的逻辑关系。

 (4)为解决(3)的问题,在二叉树的顺序存储中,一定要把二叉树的结点编号与完全二叉树对应起来,如下图所示:

 ①可以反应结点之间的逻辑关系:

        Ⅰi结点的左孩子:2i;

        Ⅱi结点的右孩子:2i+1;

        Ⅲi结点的父结点:\left \lfloor \frac{i}{2} \right \rfloor

        Ⅳi结点所在的层次: \left \lceil log_{2}^{}(n+1)\textrm{} \right \rceil\left \lfloor log_{2}^{}n\textrm{} \right \rfloor+1

②但无法直接判断左孩子右孩子或i结点是否是叶子/分支结点,可以:

        Ⅰ判断i是否有左孩子:首先我们知道2i是i的左孩子结点的位置,然后用isEmpty来判断这个位置空不空,不空则有左孩子;

        Ⅱ判断i是否有右孩子: 首先我们知道2i+1是i的右孩子结点的位置,然后用isEmpty来判断这个位置空不空,不空则有右孩子;

        Ⅲ判断i是否是叶子/分支结点:根据ⅠⅡ判断i有没有左右孩子,无则叶子,有则分支。

(5)二叉树的顺序存储的弊端:需要开辟大量的存储单元,如果不是完全二叉树的话,会造成很多存储空间的浪费,所以顺序存储结构只适合存储完全二叉树。


2.链式存储

(1)代码实现:

typedef struct BiTNode {
	int data;								//数据域
	struct BiTNode* lchild, * rchild;		//左右孩子指针
}BiTNode,*BiTree;

(2)如图所示:

 (3)由于每个结点都有两个指针域,如果一个二叉树有n个结点的话,那么它一共应该有2n个指针域。除了根结点,每个结点头上都会连一个指针,也就是有n-1个结点头上都会连一个指针,则剩下n+1个指针指向NULL,即n个结点的二叉链表共有n+1个空链域(可用于构造线索二叉树)。

(4)构造二叉链表:

struct ElemType {
	int value;
};

typedef struct BiTNode {
	int data;								
	struct BiTNode* lchild, * rchild;		
}BiTNode, * BiTree;

int main()
{
	//定义一棵空树
	BiTree root = NULL;

	//插入根结点
	root = (BiTree)malloc(sizeof(BiTNode));
	root->data = { 1 };
	root->lchild = NULL;
	root->rchild = NULL;

	//插入新结点
	BiTNode* p = (BiTNode*)malloc(sizeof(BiTNode));
	p->data = { 2 };
	p->lchild = NULL;
	p->rchild = NULL;
	root->lchild = p;		//作为根结点的左孩子
}

(5)三叉链表

        ①对于二叉链表来说,想要找到某个结点的父结点是很困难的,只能从根结点开始遍历寻找,如果结点足够多的情况下,这将是一个巨大的工程。所以引出方便寻找父结点的三叉链表:

        ②代码实现:

struct ElemType {
	int value;
};

typedef struct BiTNode {
	ElemType data;
	struct BiTNode* lchild, * rchild;
	struct BiTNode* parent;
}BiTNode,*BiTree;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值