树与二叉树
Start from 2024年4月10日,8:12:01
树的基本概念
祖先、子孙、双亲、孩子、兄弟、堂兄弟
- 祖先:
头上
的全部。比如说K的,EBA全是他祖先 - 子孙:
地下
的全部。比如说B的,EFKL全是子孙 - 双亲:头上那
一个
,根没有双去哪 - 兄弟:仅限
同一个双亲
的隔壁,比如说F的兄弟就是E - 堂兄弟:那一层的都是
结点的度和树的度
- 结点的度:全部度的总和
- 树的度:结点的最大的度
结点的深度、高度和层次
深度从下往上数,高度从上往下数(可以从1/0开始数)
有序树和无序树
路径和路径长度
森林
由m个互不相交的树的集合组成。
树的性质
结点数=总度数+1 (n=m+1)
每个结点都有个天线,除了根没有,补个1就是总结点数
度=m的树第i层最多有$m^{i-1} $个结点
1->m->
->->
最多结点数
用等比数列来推,
a1=1,q=m,在上下同*-1即可得到
最少结点数
度=m,结点数=n,最小高度也是一样的(类似于h=n)
度=m,结点数=n,最大高度 h=n-m+1
n-m是把最后一层m个节点减掉,然后加上1就是高度
总结点数两个公式
第二个公式可以理解为度数为m的节点引出m个分支,好比是天线,但是根节点没有天线所以+1
延伸
总度数=总分支数
会用到的=>
二叉树
与度=2的有序树区别
- 度=2的树至少3个结点,但是二叉树可以为空
- 度=2的左右次序是相对另一个孩子而言的,如果只有一个就
不用分左右次序
,但是二叉树是需要的
几种特殊的二叉树
满二叉树
:完全二叉树
:- 若i≤[n/2]
向下取整
后,则结点 i 为分支结点,否则为叶结点 - 叶结点只可能在
最大的两层
上出现。对于下面的叶结点,都靠左 - 若有度为1的结点,则最多只可能有一个,且该结点
只有左孩子
而无右孩子。 - 按层序编号后,一旦出现某结点(编号为i)为叶结点或只有左孩子,则编号大于i的结点均为叶结点。(参考12号节点)
- 若n为
奇数
,则每个分支结点都有
左孩子和右孩子;若n为偶数
,则编号最大
的分支结点(编号为n/2)只有左孩子
,没有右孩子,其余分支结点左、右孩子都有。
- 若i≤[n/2]
二叉排序树
:左节点大于右节点
总结篇
二叉树的顺序存储
记得 找父节点是i/2之后向下取整
判断i是否为叶子分支节点
链式存储
二叉树求空指针域
n个结点、2n个指针域,每个结点带一个天线但是root无,所以被占用的指针域有n-1个
空指针域=2n-(n-1)=n+1
三叉树空指针域or三叉链式带父节点的
需要看场合来分析,比如说三叉树的就是3n个指针域
三叉链式带父节点的那种是二叉树
错题
5.2.06
08
14完全二叉树 n求叶结点数
完全二叉树 叶结点数求结点数最大最少值
最少的话,就直接那几个叶子节点就是最后一层
最多的话,那几个叶子节点是倒数第二层的最右边
总结
爆率最高:
- 当前层结点数:
- 总结点数:
- 完全二叉树第i个的祖先:[i/2]向下取整
- 完全二叉树
- n=2k为偶数:n1=1,n0=k,n2=k-1
- n=2k-1为奇数:n1=0,n0=k,n2=k-1
- 完全二叉树高度常用[]
遍历
请务必记住分支节点逐层展开法
还有从你的全世界路过法
层次遍历
- 根节点入队
- 如果队列不空,出队一个并访问该节点,将其左右孩子入队
- 直到队列为空
由遍历序列构造二叉树
无论哪个遍历都得加上中序遍历才能确定唯一的二叉树
前序+中序
这个方法屌啊,由前序遍历找到根节点
,再区分左右
线索二叉树
注意,线索二叉树的数据结构有变
typedef struct TreadNode{
ElemType data;
struct ThreadNode *lchild,*rchild;
int lflag,rflag;//tag=0为指向孩子,1为线索
}
注意,算法中的
判断条件,有点离谱的
加入左节点的:
p->lchild==NULL
加入右节点的,不会一开始就用p判断p->rchild==NULL,因为要将pre指向后驱节点
所以判断条件为
pre!=NULL&&pre->rchild==NULL
最后遍历完,注意处理最后一个节点的right=NULL
先序线索化可能会出现的转圈问题
在根节点加入线索后,第一个左边递归需要判断是不是左孩子线索
中序线索二叉树的遍历
找中序后继
找中序后继:
- 找到第一个被中序遍历的节点(就是最左下角)
- while(p->ltag==0)p=p->lchild;
- 意思是找到最后一个左下角不带线索的
- 找p的后继结点:
- 如果tag=1(不是叶子节点),右孩子就是线索,就是中序后继
- 如果tag=0(后继有人)要找
右节点的最左下角的
,中序是左根右,左边会递归 然后 再回溯到根输出根
- visit
找中序前驱
逐层展开法看上去真的挺好用的
先序
找先序前驱
后续后驱
总结
不用背,现推
中序 | 先序 | 后续 | |
---|---|---|---|
找前驱 | √ | × | √ |
找后继 | √ | √ | × |
除非有三叉链表实现找爹
森林
存储结构
双亲表示法(顺序)
优点:找双亲节点方便
缺点,找孩子不方便,要遍历数组
孩子表示法(顺序+链式)
优点:找孩子方便
缺点:找爹不行
孩子兄弟表示法(链式)
总结
森林、树、二叉树的转换
主要为孩子兄弟表示法为核心存储
左孩子
,右兄弟
兄弟右指针
用糖葫芦串起来
孩子左指针
挂下面