文章目录
- 1 树的基本概念
- 1.1 树的形式定义
- 1.2 树的递归定义
- 1.3 树的基本术语
- 1.4 二叉树的递归定义
- 1.5 存储方法
- 1.6 满二叉树VS完全二叉树
- 2 二叉树的性质
- 3 代码实现
1 树的基本概念
1.1 树的形式定义
- D为树T中包含n个结点的有限集合,R为树中结点之间关系的集合。
- 当n=0时,树为空树;当n>0时,R是D上某个二元关系的集合,满足以下条件:
- 有且仅有一个结点,称为根结点,该结点没有直接前驱结点;
- 除根结点外,每个结点有且仅有一个前驱结点;
- D中每个结点可以有零个或多个后继结点;
1.2 树的递归定义
- 树是由n(n≥0)个结点组成的有限集T。
- 当n=0时,它是一个空树;当n>0时,它满足两个条件:
- 有且仅有一个特定的结点,称为根结点。
- 除根结点以外的其余结点分为m个(m≥0)互不相交的有限集T1、T2、……Tm,其中每个集合又都是一棵树,称T1、T2、……Tm为根结点的子树。
1.3 树的基本术语
- 结点:树的数据元素
- 结点的度:该结点的分支的个数
- 树的度:树中所有结点的度的最大值
- 结点的层次:从根到该结点的层数(根结点算第一层)
- 树的深度:所有结点的层次的最大值
- 根结点:在非空树中,无前驱结点的结点
- 分支结点:度不为0的结点
- 叶结点:度为0的结点
- 孩子结点:结点的子树的根
- 双亲结点:孩子结点的根结点
- 兄弟结点:具有共同双亲的结点
- 堂兄弟结点:双亲互为兄弟的结点
- 祖先结点:从根到该结点的所经历的所有结点
- 子孙结点:以某结点为根的子树中的任一结点
1.4 二叉树的递归定义
二叉树是结点的有限集合,这个有限集,或为空集,或由一个根结点及两棵互不相交的,分别叫作这个根的左子树和右子树的二叉树组成。
【注意】二叉树不是树的特殊情况。
1.5 存储方法
双亲表示法——求父结点方便
孩子表示法——求子结点方便
双亲孩子表示法—求父结点和子结点方便
二叉树表示法——把一个普通树转化成二叉树来存储
1.6 满二叉树VS完全二叉树
满二叉树
- 定义:深为
k
且有2k−12^k-12k−1个结点的二叉树。- 编号:约定编号从根开始,自上而下,自左而右,给二叉树中的每个结点一个从1开始的连续的编号。
完全二叉树
- 定义:深为
k
且有n
个结点的二叉树,当且仅当其每一个结点都与深度为k
的满二叉树中编号从1至n的结点一一对应。
满二叉树是完全二叉树,反之则不一定!
2 二叉树的性质
- 在二叉树的第 i 层上至多有 2i−12^{i-1}2i−1个结点 (i≥1i\geq1i≥1)
证明:
(1)i=1
时,只有一个根结点,2i−12^{i-1}2i−1 =202^020= 1,结论正确;
(2)假设n=k-1
命题成立,即第k-1
层上至多有 2k−22^{k-2}2k−2 个结点,则当n=k
时,每个结点至多有两棵子树;
则k
层结点最多为k-1
层的2倍,故s<=2∗2k−2=2k−1s<=2*2^{k-2}=2^{k-1}s<=2∗2k−2=2k−1,第i
层至多有 2i−12^{i-1}2i−1 个结点;
(3)由归纳法,即得证。
- 深度为 k 的二叉树至多有2k−12^k-12k−1个节点(k≥1k\geq1k≥1)
20+21+…+2k-1=2k-1(利用等比数列求和公式得到结果)
- 对任何一颗二叉树 T,如果其终端结点树为 n0n_0n0,度为 2 的结点数为 n2n_2n2,则 n0n_0n0 = n2n_2n2+1
证明:
终端结点数就是叶结点数了,而一颗二叉树,除了叶结点外,剩下的就是度为 1 和 2 的结点数了,我们设 n1n_1n1 为度是 1 的结点数,则树 T 的总结点数为n = n0n_0n0 + n1n_1n1 + n2n_2n2
再换一个角度,数一下二叉树中连接线的总数,由于根节点没有双亲,所以一个二叉树中,连接线数等于结点树-1,n1n_1n1 的度为 1 所以它仅有一条连接线,n2n_2n2同理,代数表达式就是
n−1n-1n−1 = n1n_1n1 +2n22n_22n2
再结合等式
n = n0n_0n0 + n1n_1n1 + n2n_2n2
推导出
n0n_0n0 + n1n_1n1 + n2n_2n2-1 = n1n_1n1 + 2n22n_22n2
所以:
n0n_0n0 = n2n_2n2 + 1
- 具有 n 个结点的完全二叉树的深度为 [log2n][\log_2 n][log2n] + 1 ,([x]代表不大于 x 的最大整数)
证明:
1)对于满二叉树,深度为 k 的满二叉树至多有2k−12^k-12k−1个节点(k≥1k\geq1k≥1)
那么由:n=2k−1n=2^k-1n=2k−1
可以倒推
k=log2(n+1)k=\log_2(n+1)k=log2(n+1)
2)对于完全二叉树,它的结点数一定少于等于同样深度的满二叉树 2k−12^k-12k−1,但一定多于 2i−1−12^{i-1}-12i−1−1,即:
2i−1−1<n≤2k−12^{i-1}-1<n\leq2^k-12i−1−1<n≤2k−1
所以
2i−1≤n<2k2^{i-1}\leq n < 2^k2i−1≤n<2k
两边取对数:
2i−1≤n<2k2^{i-1}\leq n < 2^k2i−1≤n<2k
而 k 又是整数:
k=[log2n]+1k = [\log_2 n] + 1k=[log2n]+1
- 对于一个有 n 个结点的完全二叉树(或满二叉树)的结点按层序顺序从左到右编号,对任意结点 i 有:
1)如果 i = 1,那么结点 i 为该树的根,无双亲;若 i > 1 ,则其双亲是结点 [i/2]
2)如果 2i > n,则结点无左孩子(结点 i 为叶子结点),否则其左孩子结点是 2i
3)如果 2i + 1 > n,则结点 i 无右孩子,否则其右孩子是结点 2i + 1
3 代码实现
创建二叉树:
#include <stdio.h>
#include <stdlib.h>typedef char ElementType;
typedef struct Binary {ElementType data;struct Binary *lchild;struct Binary *rchild;
} *BinaryTree;/* Recursive implementation 1 */
BinaryTree CreateBinaryTree_1(void)
{BinaryTree bt;char ch;scanf("%c", &ch);if (ch == '#') {bt = NULL;} else {bt = (BinaryTree)malloc(sizeof(struct Binary));bt->data = ch;bt->lchild = CreateBinaryTree_1();bt->rchild = CreateBinaryTree_1();}return bt;
}/* Recursive implementation 2 */
void CreateBinaryTree_2(BinaryTree *bt)
{char ch;scanf("%c", &ch);if (ch == '#') {*bt = NULL;} else {*bt = (BinaryTree)malloc(sizeof(struct Binary));(*bt)->data = ch;CreateBinaryTree_2(&((*bt)->lchild));CreateBinaryTree_2(&((*bt)->rchild));}
}void PreviousOrderTraverse(BinaryTree T)
{if (T == NULL) {return;}printf("%c", T->data);PreviousOrderTraverse(T->lchild);PreviousOrderTraverse(T->rchild);
}int main(void)
{BinaryTree bt;// bt = CreateBinaryTree_1();CreateBinaryTree_2(&bt);PreviousOrderTraverse(bt);return 0;
}
运行结果: