树与二叉树
01 树的基本概念
- 树的定义:树是
n
(
n
>
=
0
)
n(n>=0)
n(n>=0)个结点的有限集合,
n
=
0
n =0
n=0时为空树,这是一种特殊情况,在任意空树中应该满足:
- 有且只有一个特定的称为根的结点
- 当 n > 1 n>1 n>1时,其余结点可分为m(m>0)个互不相交的有限集合 T 1 , T 2 , . . . . . T m {T}_{1},{T}_{2},.....{T}_{m} T1,T2,.....Tm其中每个集合本身又是一棵树,并且称为根结点的子树
- 树结构有两个特点:
- 树的根结点没有前驱结点,除根结点外的所有结点有且只有一个前驱结点
- 树中所有结点可以有0个或者多个后继结点
- 基本术语:
- 度:树中一个结点的子结点个数称为该结点的度,树中结点的最大度数称为树的度
- 深度:从根结点开始自顶而下逐层累计
- 高度:从叶结点开始自底向上逐层累加
- 层次:从根结点开始定义
- 基本性质:
- 树中的结点数等于所有结点的度数加1
- 度为m的树中第i层上至多有 m i − 1 {m}^{i-1} mi−1个结点(i>=1)
- 高度为h的m叉树至多有 ( m h − 1 ) / ( m − 1 ) (m^{h}-1)/(m-1) (mh−1)/(m−1)个结点
- 具有n个结点的m叉树的最小高度为 [ l o g m ( n ( m − 1 ) + 1 ) ] [log_{m}(n(m-1)+1)] [logm(n(m−1)+1)]
02 二叉树
-
定义:每个结点至多只有两棵子树,并且子树有左右之分,其次序不能任意颠倒
-
二叉树的种类:
- 满二叉树
- 完全二叉树
- 排序二叉树
-
二叉树的存储结构
-
顺序存储结构:比较合适用来存储满二叉树或者完全二叉树
-
链式存储结构:
typeef struct BiTNode{ ElemType data; //数据域 struct BiTNode *lchild, *rchild //左右孩子指针 }BiTNode, *BiTree;
-
-
二叉树的遍历和线索二叉树
- 先序遍历
void PreOrder(BiTree T) { if(T!=NULL) { visit(T); //访问根节点 PreOrder(T->lchild); // 递归遍历左子树 PreOrder(T->rchild); // 递归遍历右子树 } }
- 中序遍历
void InOrder(BiTree T) { if(T!=NULL) { InOrder(T->lchild); // 递归遍历左子树 visit(T); //访问根节点 InOrder(T->rchild); // 递归遍历右子树 } }
- 后序遍历
void PostOrder(BiTree T) { if(T!=NULL) { PostOrder(T->lchild); // 递归遍历左子树 PostOrder(T->rchild); // 递归遍历右子树 visit(T); //访问根节点 } }
- 层次遍历
void LevelOrder(BiTree T) { IninQueue(Q); //初始化队列 BiTree p; EnQueue(Q, T); //将根元素入队 while(!IsEmpty(Q)) //队列不空循环 { DeQueue(Q, p); //队头元素出队 visit(p); //访问当前p所指向结点 if(p->lchile!=NULL) { EnQueue(Q, p->lchild); //左子树不为空,则左子树入队列 } if(p->rchile!=NULL) { EnQueue(Q, p->rchild); //右子树不为空,则右子树入队列 } } }
-
线索二叉树
- 定义,传统的链式存储结构仅能体现结点的父子关系,不能直接体现每个结点的前驱和后继。
- 线索二叉树通常规定,若无左子树,令lchild指向其前驱结点,若无右子树,令rchild指向其后继结点。通知增加标识符rtag和ltag表示当前结点的指针域指向的是子结点还是前驱。
typedef struct ThreadNode { Elemtype data; struct ThreadNode *rchild, *lchild; int ltag, rtag; }ThreadNode, *ThreadTree;
- 定义,传统的链式存储结构仅能体现结点的父子关系,不能直接体现每个结点的前驱和后继。
03 树和森林
-
树的存储结构
- 双亲表示法:采用一组连续空间来存储每个结点,同时在每个结点中增设一个伪指针,指示其双亲结点在数组中的位置
- 孩子表示法:将每个结点的孩子结点都用单链表连接起来的一种线性结构
- 孩子兄弟表示法:即以二叉链表作为树的结点,有三个部分:结点值,指向结点的第一个孩子结点的指针及指向结点下一个兄弟结点的指针
-
树、森林与二叉树的转换
- 树转换为二叉树的规则:每个结点左指针指向它的第一个孩子结点,右指针指向它在树中的相邻兄弟节点
- 根节点没有兄弟,所有树转换为二叉树是没有右子树
-
森林转换成二叉树:
- 森林转换二叉树,和树转换为二叉树规则类似
-
二叉树转换为森林:
- 若二叉树为非空,则二叉树的根及其左子树作为第一颗树的二叉树形式,二叉树的根的右子树又可视为一个由除第一颗树外的森林转换后的二叉树
-
树与森林的遍历:
遍历关系对应 树 森林 二叉树 先根遍历 先序遍历 先序遍历 后根遍历 中序遍历 中序遍历
04 树与二叉树的应用
-
二叉排序树
- 若左子树非空,则左子树上的所有关键字值均小于根节点的关键字值
- 若右子树非空,则右子树上的所有关键字值均大于根节点的关键字值
- 左右子树本身也是二叉排序树
- 删除结点后注意:
- 右子树为空,用左子女去补
- 左子树为空,用右子女去补
- 左右子树均不为空,在右子树找中序第一个子女去补
-
二叉平衡树:为避免树的高度增长过快,左右子树高度差绝对值不超过1
- LL平衡
- RR平衡
- LR平衡
- RL平衡
-
哈夫曼树:最优二叉树(在带权重下,总路径最短)