树
一、树的基本概念
空树:指节点数为0的树。
非空树:有且仅有一个根节点。
没有后继节点的节点被称为叶子节点。
有后继的节点被称为分支节点。
除了根节点外,任何一个节点都有且仅有一个前驱。
每个节点可以有0个或多个后继
树的性质
性质1:
度为m的树 | m叉树 |
---|---|
任意节点的度<=m | 任意节点的度<=m |
至少有一个节点的度=m | 允许所有节点的度都<m |
一定是非空树,至少有m+1个节点 | 可以是空树 |
性质2:
度为m的树第i层至多有
m
i
−
1
m^{i-1}
mi−1 (i>=1)。
m叉树第i层至多有
m
i
−
1
m^{i-1}
mi−1 (i>=1)。
性质3:
高度为h的m叉树至多有
m
h
−
1
m
−
1
\frac{m^h-1}{m-1}
m−1mh−1
性质4:
高度为h的m叉树至少有h个节点。
高度为h,度为m的树至少有h+m-1个节点。
性质5:
具有n个节点的m叉树的最小高度为
log
m
(
n
(
m
−
1
)
+
1
)
\log_m{(n(m-1)+1)}
logm(n(m−1)+1)
二叉树
二叉树的基本术语
二叉树的定义
二叉树是另一种树形结构,其特点是每个结点至多只有两棵子树( 即二叉树中不存在度大于2的结点),并且二叉树的子树有左右之分,其次序不能任意颠倒。
特殊的二叉树
满二叉树
一颗高度为h,且含有
2
h
−
1
2^h-1
2h−1个节点的二叉树。只有最后一层有叶子节点,不存在度为1的节点,按层序从1 开始编号节点i的左孩子为2i,右孩子为2i+1,节点i的父节点为i/2。
完全二叉树
当且仅当其每个节点都与高度为h的满二叉树中编号1~n的节点一一对应,称为完全二叉树。
二叉排序树
左子树上所有结点的关键字均小于根结点的关键字;右子树上的所有结点的关键字均大于根结点的关键字;左子树和右子树又各是一棵二叉排序树。
平衡二叉树
树上任一结点的左子树和右子树的深度之差不超过1。
二叉树的性质
1.设非空二叉树中度为0、1、2的节点个数分别为
n
1
,
n
2
,
n
3
n_1,n_2,n_3
n1,n2,n3则
n
0
=
n
2
+
1
n_0=n_2+1
n0=n2+1
2.二叉树第i层至多有
2
i
−
1
2^{i-1}
2i−1
3.高度为h的二叉树至多有
2
h
−
1
2^h-1
2h−1个节点
4.具有n个节点的完全二叉树的高度h为
log
2
(
n
+
1
)
\log_2{(n+1)}
log2(n+1)或
log
2
n
+
1
\log_2n+1
log2n+1
5.对于完全二叉树,可以由节点数n推出度为0、1、2的节点个数
n
1
,
n
2
,
n
3
n_1,n_2,n_3
n1,n2,n3
若完全二叉树有2k个节点(偶数)则有
n
1
=
1
,
n
0
=
k
,
n
2
=
k
−
1
n_1=1,n_0=k,n_2=k-1
n1=1,n0=k,n2=k−1
若完全二叉树有2k-1个节点(奇数)则有
n
1
=
0
,
n
0
=
k
,
n
2
=
k
−
1
n_1=0,n_0=k,n_2=k-1
n1=0,n0=k,n2=k−1
二叉树的存储结构
二叉树的顺序存储
二叉树的顺序存储是指用一组地址连续的存储单元依次自上而下、自左至右存储完全二叉树上的结点元素,即将完全二叉树上编号为 i 的结点元素存储在一维数组对应的下标中。
二叉树的链式存储
二叉树每个结点最多有两个孩子,所以为它设计一个数据域和两个指针域是比较自然的想法,我们称这样的链表叫做二叉链表。
/*二叉树的二叉链表结点构造定义*/
/*结点结构*/
typedef struct BiTNode{
TElemType data; //结点数据
struct BiTNode *lchild, *rchild; //左右孩子指针
} BiTNode, *BiTree;
二叉树的遍历
线序遍历
先序遍历(PreOrder) 的操作过程如下:
若二叉树为空,则什么也不做,否则,
1)访问根结点;
2)先序遍历左子树;
3)先序遍历右子树。
void PreOrder(BiTree T){
if(T != NULL){
visit(T); //访问根节点
PreOrder(T->lchild); //递归遍历左子树
PreOrder(T->rchild); //递归遍历右子树
}
}
中序遍历
中序遍历( InOrder)的操作过程如下:
若二叉树为空,则什么也不做,否则,
1)中序遍历左子树;
2)访问根结点;
3)中序遍历右子树。
void InOrder(BiTree T){
if(T != NULL){
PreOrder(T->lchild); //递归遍历左子树
visit(T); //访问根节点
PreOrder(T->rchild); //递归遍历右子树
}
}
后续遍历
后序遍历(PostOrder) 的操作过程如下:
若二叉树为空,则什么也不做,否则,
1)后序遍历左子树;
2)后序遍历右子树;
3)访问根结点。
void PostOrder(BiTree T){
if(T != NULL){
PreOrder(T->lchild); //递归遍历左子树
PreOrder(T->rchild); //递归遍历右子树
visit(T); //访问根节点
}
}