二叉树
树的基本定义
树
n个节点构成的有限集,在一个非空的集合:(1)中有且仅有一个特定的点称为 根(Root)
(2)当 n>1 时其余节点可以分为m个互不相交有限集合,每个集合也是一棵树,称为 子树(SubTree)
度(Degree)
节点拥有的子树数,度为0的点称为 叶子(Leaf)
深度(Depth)
树中节点的最大层次,又称为高度
森林(Forest)
是
m
(
m
≥
0
)
m(m\geq0)
m(m≥0)棵互不相交的数的集合
二叉树的定义及性质
定义
每个节点至多只有两棵子树(即二叉树中不存在度大于2的节点),并且,二叉树的子树有左右之分为顺序树
性质
性质一
在二叉树的第 i i i层上至多有 2 i − 1 2^{i-1} 2i−1 个节点( i ≥ 1 i \geq 1 i≥1)
利用归纳法可以证明:
i = 1 i= 1 i=1的时候只有一个根节点,显然 $ 2^{i-1} = 2^0 = 1$ 是对的
第 i − 1 i-1 i−1层 上最多有 2 i − 2 2^{i-2} 2i−2个节点,因为二叉树的各节点的度为2,所以第 i i i层与第 i − 1 i-1 i−1层的最大几点之间差两倍,即为 2 × 2 i − 2 2 \times 2^{i-2} 2×2i−2
性质二
深度为 k k k的二叉树至多有 2 k − 1 2^k-1 2k−1个节点 ( k ≥ 1 ) (k\geq1) (k≥1)
由性质一可知深度为 k k k的二叉树最大的节点数为
∑ i = 1 k ( 第 i 层 上 的 最 大 节 点 数 ) = ∑ i = 1 k 2 i − 1 = 2 k − 1 \sum _{i=1}^{k}(第i层上的最大节点数) = \sum _{i=1}^{k}2^{i-1} = 2^k -1 i=1∑k(第i层上的最大节点数)=i=1∑k2i−1=2k−1
性质三
对于任意一棵二叉树,如果其叶子节点数目为 2 0 2_{0} 20度为2的节点数为 2 2 2_{2} 22,则会有 2 0 = 2 2 + 1 2_{0} = 2_{2}+1 20=22+1
设度为1的节点数目为 2 1 2_{1} 21所以二叉树中总共的节点数目为
n = n 0 + n 1 + n 2 n=n_0+n_1+n_2 n=n0+n1+n2
假设分支数为 B B B所以除了根节点外可以得知, n = B + 1 n = B+1 n=B+1,然后又可以得分支节点都是由度为2和度为1的节点构成的所以有 B = n 1 + 2 n 2 B=n_1+2n_2 B=n1+2n2,所以得
n = n 1 + 2 n 2 + 1 n = n_1+2n_2+1 n=n1+2n2+1
所以由以上两个式子可以退出:
n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1
满二叉树
一棵深度为
K
K
K的树且有
2
k
−
1
2^k-1
2k−1个结点的二叉树
完全二叉树
一棵深度为
K
K
K的树,且从上到下,从左到右的为每一个节点编号,其各个结点的编号数与深度为
K
K
K的满二叉树的编号相同,即完全二叉树为同深度的满二叉树从右往左丢叶子结点形成的(具体可以参考书中的图)
性质四
具有 n n n个节点的完全二叉树的深度为 ⌊ l o g 2 n ⌋ + 1 ( 其 中 ⌊ x ⌋ \left\lfloor log2n\right\rfloor+1(其中\left\lfloor x\right\rfloor ⌊log2n⌋+1(其中⌊x⌋表示不大于 的 整 数 ) 的整数) 的整数)
性质五
对于一个有n个结点的完全二叉树,对其进行从上到下,从左到右标号,则对于任意一个节点i有:
- 如果 i = 1 i=1 i=1则此时为二叉树的根,无双亲;如果 i > 1 i>1 i>1,则它的双亲节点 i i i为结点 [ i / 2 ] [i/2] [i/2]
- 如果 2 i > n 2i>n 2i>n,则结点 i i i没有左孩子,此时为叶子节点,反之,其左儿子为结点 [ 2 i ] [2i] [2i]
- 如果 2 i + 1 > n 2i+1>n 2i+1>n,则结点 i i i没有右孩子,反之,其右儿子为结点 [ 2 i + 1 ] [2i+1] [2i+1]
二叉树的存储结构
顺序存储结构
顺序存储的表示
#define MAX_TREE_SIZE 100 //表示二叉树最大的节点数
typedef TElemType SqBiTree[MAX_TREE_SIZE];
SqBiTree bt;
其中如果点不存在就表示为0,可以很容易得知此种存储方式很实用于完全二叉树.
出现最坏的情况为,深度为k的二叉树只有k个结点,此时我们需要一个 2 k − 1 2^k-1 2k−1的一维数组进行存储
链式存储结构
链式存储的表示
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
struct BiTNode *parent;
}BiTNode,*BiTree;
遍历二叉树
主要存在三种遍历方法,先序,中序,后序
先序遍历
:首先访问根,再先序遍历左(右)子树,最后先序遍历右(左)子树
中序遍历
:首先中序遍历左(右)子树,再访问根,最后中序遍历右(左)子树
后序遍历
:首先后序遍历左(右)子树,再后序遍历右(左)子树,最后访问根
代码实现
//先序
void preOrderTraverse(BTT T) {
if(T == nullptr) return;
cout<<T->data;
preOrderTraverse(T->lc);
preOrderTraverse(T->rc);
}
//中序
void inOrderTraverse(BTT T) {
if(T == nullptr) return;
inOrderTraverse(T->lc);
cout<<T->data;
inOrderTraverse(T->rc);
}
后序
void postOrderTraverse(BTT T) {
if(T == nullptr)
return;
postOrderTraverse(T->lc);
postOrderTraverse(T->rc);
cout<<T->data;
}
根据先序和中序求二叉树,或者根据中序和后序求二叉树
第一步:在先序(第一个)或者后序(最后一个)中找到根节点
第二步:在中序中以根节点为中心,分为两个部分前为左子树,后为右子树
第三步:根据划分在在先序和后序中标记出来,并按照第一步找子树的根节点
… 重复操作
Huffman树
赫夫曼树又称为最优二叉树,即 W P L ( W P L = ∑ k = 1 n w k l k 其 中 w k 为 结 点 的 权 值 , l k 为 结 点 的 深 度 ) WPL(WPL =\sum_{k=1}^{n}w_kl_k其中w_k为结点的权值,l_k为结点的深度) WPL(WPL=∑k=1nwklk其中wk为结点的权值,lk为结点的深度) 最小的树
构建Huffman树
-
根据给定的 n n n个权值{ w 1 , w 2 , . . . , w n w_1,w_2,...,w_n w1,w2,...,wn}构成 n n n 棵二叉树的集合 F = F= F={ T 1 , T 2 , . . . , T n T_1,T_2,...,T_n T1,T2,...,Tn} ,其中每一棵二叉树 T i T_i Ti 只有一个带有权 w i w_i wi 的根节点其左右子树为空
-
在 F F F 中选取第二颗根节点的权值最小的树作为左右子树构建一棵新的二叉树,且置新的二叉树的根节点的权值为其左右子树权值的和
-
在 F F F 中删除这两棵树,同时将新得到的二叉树加入 F F F 中
-
重复(2)和(3),直到 F F F 只含一棵树为止
即反复选取当前权值最小的两棵树进行建树
Huffman编码
从根节点开始,向左延伸为0,向右延伸为1