树的度:树中拥有最多子结点数量的结点拥有的结点数,二叉树的度不一定是2,可能是1或0
树的基本知识:
根:最上方的结点;叶子:没有子结点的结点;只有一个结点的树,该结点既是根又是叶子。
树的结点数为n,则去掉根结点后有n-1个子结点,即n-1条边;
若此树的度为k,则具有kn个指针,其中n-1个已用,剩余(k-1)n+1个空指针;
因n个结点的树最多有n-1个结点,即n-1条边,因此n结点m条边的图要转为树,至少需要砍去m-n+1条边
树的度为k,ni代表度为i的结点的数量,则 n0+n1+...+nk = 1+n1+2n2+3n3+...knk
完全二叉树:结点从左往右陆续分配,一层满了才到下一层的树为完全二叉树。
若从左向右,从上到下编号(用数组表示):从1开始编号,则编号为k的结点,其左子结点编号为2k,右子结点为2k+1,父节点为ground( k / 2 )
从0开始编号,则编号为k的结点,其左子结点编号为2k+1,右子结点为2k+2,父节点为ground( (k-1) / 2 )
满二叉树:每一层都满的二叉树
遍历:前序遍历:父节点->左子结点->右子结点 中序:左子结点->父节点->右子结点 后序:左子结点->右子结点->父节点
搜索二叉树:左子结点<父结点<右子结点,用中序遍历
平衡因子:结点的左子树深度减右子树深度
设F是一个森林,B是由F变换得到的二叉树。若F中有n个非终端结点,则B中右指针域为空的结点有()个:
设二叉树结点数为X,则有:右空链域+右非空链域=X(因为每个节点有一个右链域)
同时由二叉树性质:X=左非空链域+右非空链域+1
然后如果二叉树中某节点有左孩子,则在原来的树中该节点一定为非叶节点,因此:左非空链域=n
=> X=n+右非空链域+1,代入X=右空链域+右非空链域,得n+1=右空链域,原题得解
求树对应的二叉树中无右孩子的结点个数:
example:Q:已知一棵有2011个结点的树,其叶结点个数为116,该树对应的二叉树无右孩子的结点个数为
A:转换出来的二叉树中,一共有2011*2个链域,其中左右链域各2011个。设非空的左链域有XL个,非空的右链域有XR个,那么XL+XR+1=2011(总节点数为根节点加左右孩子数)且因为二叉树是由树转化而来,因此节点在树中至少要有一个孩子才能在转化为二叉树后有左孩子(也就是非叶节点),也就是说有2011-116个节点在二叉树中有左孩子,因此XL=2011-116,代入上式可得2011-116+XR+1=2011,因此XR=115。由此,空的右链域=2011(右链域数)-XR=1896个,得解
线索树:
对于n个结点的二叉树,在二叉链存储结构中有n+1个空链域,利用这些空链域存放在某种遍历次序下该结点的前驱结点和后继结点的指针,
这些指针称为线索,加上线索的二叉树称为线索二叉树。分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种
后续线索树:
在后序线索二叉树中查找结点*p的后继:若结点*p为根,则无后继;若结点*p为其双亲的右孩子,则其后继为其双亲;
若结点*p为其双亲的左孩子,且双亲无右子女,则其后继为其双亲;
若结点*p为其双亲的左孩子,且双亲有右子女,则结点*p的后继是其双亲的右子树中按后序遍历的第一个结点。
所以,求后序线索二叉树中结点的后继要知道其双亲的信息,要使用栈,所以说后序线索二叉树是不完善的。
哈夫曼树(最优二叉树):
哈夫曼编码:
树的表示:
(1)parent表示法(数组表示):结点全放在数组中,每个结点储存parent的index
(2)child表示法:每个结点有指针指向每个子结点
(3)sibling表示法(二叉链表表示法):每个结点含指向左子结点和右兄弟的指针
数组表示:按层次存储(完全二叉树)
生成树:连通图的所有结点的树
最小生成树:Prim算法:
1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
3).重复下列操作,直到Vnew = V:
a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V
(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;
4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。
时间复杂度:矩阵存储O(n^2),邻接表O( (v+e) log(v) )
B树:支持随机检索,不支持顺序检索(?)
一棵m阶B树(balanced tree of order m)是一棵平衡的m路搜索树。它或者是空树,或者是满足下列性质的树:
1. 定义任意非叶子结点最多只有 M 个儿子;且 M>2 ;
2. 根结点的儿子数为 [2, M] ;
3. 除根结点以外的非叶子结点的儿子数为 [M/2, M] ;
4. 每个结点存放至少 M/2-1 (取上整)和至多 M-1 个关键字;(至少 2 个关键字)
5. 非叶子结点的关键字个数 = 指向儿子的指针个数 -1;
6. 非叶子结点的关键字: K[1], K[2], …, K[M-1];且 K[i] < K[i+1] ;
7. 非叶子结点的指针: P[1], P[2], …, P[M] ;其中 P[1] 指向关键字小于 K[1] 的子树, P[M] 指向关键字大于 K[M-1] 的子树,其它 P[i] 指向关键字属于 (K[i-1], K[i]) 的子树;
8. 所有叶子结点位于同一层;
B+树:支持顺序和随机检索
树转换为二叉树
1. 加线
在所有兄弟结点之间加一条连线。
2. 去线
树中的每个结点,只保留它与第一个孩子结点的连线,删除它与其它孩子结点之间的连线。
3. 层次调整
以树的根节点为轴心,将整棵树顺时针旋转一定角度,使之结构层次分明。(注意第一个孩子是结点的左孩子,兄弟转换过来的孩子是结点的右孩子)
森林转换为二叉树
1. 把每棵树转换为二叉树。
2. 第一棵二叉树不动,从第二棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树的根结点的右孩子,用线连接起来。
二叉树转换为树
是树转换为二叉树的逆过程。
1. 加线
若某结点X的左孩子结点存在,则将这个左孩子的右孩子结点、右孩子的右孩子结点、右孩子的右孩子的右孩子结点…,都作为结点X的孩子。将结点X与这些右孩子结点用线连接起来。
2. 去线
删除原二叉树中所有结点与其右孩子结点的连线。
3. 层次调整。
二叉树转换为森林
假如一棵二叉树的根节点有右孩子,则这棵二叉树能够转换为森林,否则将转换为一棵树。
1. 从根节点开始,若右孩子存在,则把与右孩子结点的连线删除。再查看分离后的二叉树,若其根节点的右孩子存在,则连线删除…。直到所有这些根节点与右孩子的连线都删除为止。
2. 将每棵分离后的二叉树转换为树。