二叉树
二叉树的定义
二叉树(Binary Tree)是 n(
n
≥
0
n \ge 0
n≥0)个结点所构成的集合,它或为空树;或为非空树。
对于非空树 T:
1) 有且仅有一个根结点。
2) 除根结点以外的其余结点分为两个不相交的子集
T
1
T_1
T1 和
T
2
T_2
T2,分别称为 T 的左子树和右子树,且
T
1
T_1
T1 和
T
2
T_2
T2 本身又都是二叉树。
二叉树区别于树的特点:
1) 每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点)。
2) 二叉树的子树有左右之分,其次序不能颠倒。
二叉树具有五种基本形态:
- 空二叉树。
- 只有一个根结点。
- 根结点只有左子树。
- 根结点只有右子树。
- 根结点左子树和右子树都有。
满二叉树
如果二叉树的所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。
满二叉树的特点:
每一层上的结点数都是最大结点数(即,每个第 i 层上有
2
i
−
1
2^{i-1}
2i−1 个结点)。
完全二叉树
深度为 k 的,有 n 个结点的二叉树,当且仅当每一个结点都与深度为 k 的满二叉树中编号从1至 n 的结点一一对应时,称之为完全二叉树。
完全二叉树的特点:
1) 叶子结点只可能在层次最大的两层上出现;
2) 对任意结点,若其右分支下的子孙的最大层次为
l
l
l,则其左分支下的子孙的最大层次必为
l
l
l或
l
+
1
l + 1
l+1。
二叉树的性质
二叉树具有下列重要特性:
性质1:在二叉树上第 i 层上至多有
2
i
−
1
2^{i-1}
2i−1 个结点。(
i
≥
0
i \ge 0
i≥0)
性质2:深度为 k(k为层次数)的二叉树至多有
2
k
−
1
2^k-1
2k−1 个结点。(
k
≥
0
k \ge 0
k≥0)
性质3:对任何一颗二叉树 T,如果其终端结点数为
n
0
n_0
n0,度为 2 的结点数为
n
2
n_2
n2 则,
n
0
=
n
2
+
1
n_0 = n_2+1
n0=n2+1。
性质4:具有 n 个结点的完全二叉树的深度为
log
2
n
+
1
\log_2 n+1
log2n+1。(
log
2
n
\log_2 n
log2n 为不大于
log
2
n
\log_2 n
log2n 的最大整数)
性质5:具有 n 个结点的完全二叉树的结点按层序编号,则对任一结点 i(
1
≤
i
≤
n
1\le i \le n
1≤i≤n),有
- 若 i = 1 i=1 i=1,则结点 i 是二叉树的根,无双亲;若 i > 1 i>1 i>1,则其双亲是结点 1 / 2 1/2 1/2。
- 若 2 i > n 2i>n 2i>n,则结点 i 无左孩子;否则其左孩子是结点 2 i 2i 2i。
- 若 2 i + 1 > n 2i+1>n 2i+1>n,则结点 i 无右孩子;否则其右孩子是结点 2 i + 1 2i+1 2i+1。
二叉树的存储结构
顺序存储结构
用一维地址连续的存储单元依次自上而下,自左至右存储完全二叉树上的结点元素;用0表示不存在的结点。
链式存储结构
typedef unsigned char TElemType;
typedef struct BiTNode
{
TElemType data; //数据域
struct BiTNode* LChild; //左孩子
struct BiTNode* RChild; //右孩子
}BiTNode, BiTree;
二叉树的遍历(递归遍历)
每个结点均被访问一次,而且仅被访问一次。
先(根)序遍历:根-左-右
/*先序遍历二叉树*/
void PreOrderTraverse(BiTree* T)
{
if (T != NULL)
{
printf("%c ", T->data);
PreOrderTraverse(T->LChild);
PreOrderTraverse(T->RChild);
}
}
中(根)序遍历:左-根-右
/*中序遍历二叉树*/
void InOrderTraverse(BiTree* T)
{
if (T != NULL)
{
InOrderTraverse(T->LChild);
printf("%c ", T->data);
InOrderTraverse(T->RChild);
}
}
后(根)序遍历:左-右-根
/*后续遍历二叉树*/
void PostOrderTraverse(BiTree* T)
{
if (T != NULL)
{
PostOrderTraverse(T->LChild);
PostOrderTraverse(T->RChild);
printf("%c ", T->data);
}
}
计算二叉树的深度
/*计算二叉树的深度*/
int Depth(BiTNode* T)
{
int m = 0;
int n = 0;
if (T != NULL)
{
m = Depth(T->LChild);
n = Depth(T->RChild);
if (m > n)
return m + 1;
else
return n + 1;
}
else
return 0;
}
测试程序
void BinaryTreeTest(void)
{
/*层序
A
B C
D E F
*/
BiTree T = { 'A',NULL,NULL };
BiTNode NewNode1 = { 'B',NULL,NULL };
BiTNode NewNode2 = { 'C',NULL,NULL };
BiTNode NewNode3 = { 'D',NULL,NULL };
BiTNode NewNode4 = { 'E',NULL,NULL };
BiTNode NewNode5 = { 'F',NULL,NULL };
T.LChild = &NewNode1;
T.RChild = &NewNode2;
NewNode1.LChild = &NewNode3;
NewNode2.LChild = &NewNode4;
NewNode2.RChild = &NewNode5;
PreOrderTraverse(&T);
printf("\n");
InOrderTraverse(&T);
printf("\n");
PostOrderTraverse(&T);
printf("\n");
printf("二叉树深度:%d\n", Depth(&T));
}