知识要点:
树的结构和主要概念,各种二叉树的结构及其特点;
二叉树的三种遍历方法的实现原理和性质,能将二叉树的遍历方法应用于求解二叉树的叶子结点个数、二叉树计数等问题,遍历的非递归实现方法;
线索化二叉树的结构和基本操作;(充分利用二叉树的空链域)
森林的定义和存储结构,森林的遍历等方法的实现;(遍历方式与二叉树一致)
基于霍夫曼树生成霍夫曼编码的方法;
最优二叉树(霍夫曼树)的构造原理和相关算法。
AVL树的定义和特点以及AVL树调整操作的实现原理;(平衡二叉树的创建与调整)
1、树
树的定义:含有n个结点的有限集合;n=0时二叉树为空树;
1)在非空二叉树 中有且只有一个被称为根的结点;
2)其余结点可以分为多个互不相交的集合,每个集合本身又是一棵树;
特点:除了根结点之外,每个结点都有前驱结点,树中所有结点可以有0个或多个后继结点。
对于含有n个结点的树,其有n-1条边;
树的相关定义(了解):
祖先结点:沿着某一路径到达结点K,K之前的所有结点都为其祖先结点;
子孙结点:从K点沿着某一路径向下,K之后的所有结点都为其子孙结点;
双亲结点:在K结点上侧,且直接与K相互关联的结点,称为K的双亲结点;
孩子结点:在K结点下侧,且直接与K相互关联的结点,称为K的孩子结点;
兄弟结点:位于同一层次上,且双亲结点相同的结点之间互为兄弟结点;
结点的度:该结点所具有的分支数;(由此结点发出的边的条数)
树的度:树中结点度的最大值;
分支结点:度非0的结点,所具有的分支数就是该结点的度;
叶子结点(终端结点):度为0的结点;
结点的层次:根结点位于第一层,由上往下层次数依次加一;
树的高度(深度):结点的最大层次数;
有序树和无序树:不区分子树的先后顺序为无序树(子树可以相互交换位置),反之称为有序树;
路径和路径长度:两个结点之间的路径即结点之间所经过的分支,分支的数目称为路径长度;
森林:多颗互不相交的树的集合;
性质:树中的结点数等于所有结点的度数加1(含有n个结点的树边数为n-1)
树中有n-1条边,所有结点的度数为n-1 ->此树中含有n个结点
m叉树中中第i层最多有m^(i-1)个结点;
第一层1个,第二程m个,第三层m^2个,数学归纳法得出第i层最多有m^(i-1)个
树高为h的m叉树最多有(m^h-1)/(m-1)个结点;
1+m+m^2+.....+m^(h-1) 等比数列求和
含有n个结点的m叉树的最小高度为 logm[n(m-1)+1]上取整;
让每一层都达到最大结点数,所形成的树高度最小;
(m^h-1)/(m-1)>=n且(m^(h-1)-1)/(m-1)<n;求解两方程得出
logm[n(m-1)+1]<=h<logm[n(m-1)+1]+1
二叉树的定义:(递归定义且为有序树子树之间不能相互变化)
要么为空树,要么满足以下定义:
1)有且只有一个被称为根的结点;
2)除了根结点之外,其余结点又分为两个互不相交的集合,每个集合又满足二叉树的定义(左右子树);
性质:叶子节点的个数等于度为2的结点个数+1(即 N0=N2+1)
N0+N1+N2=N;
N1+2N2=N-1;联立两式得出N0=N2+1;
含有n个结点的二叉树必有n+1个空指针域(可以用于二叉树的线索化);
N2=N0-1;N0+N1+N2=n;得出N1+2N0=n+1;(N0提供两个空指针域,N1提供一个空指针域)
两种特殊的二叉树:(完全二叉树和满二叉树)
满二叉树:每一层的结点数都达到最大值(即深度为k的二叉树结点数目为2^k-1,每i层结点为2^(i-1))
完全二叉树:对二叉树从根开始由右到左依次标号,与满二叉树对应的标号一致则称之为完全二叉树;
特点:叶子结点只会出现在层次最大的两层上;
性质:含有n个结点的完全二叉树的深度为,k=(log2[n])(下取整)+1;
完全二叉树中要么无度为1的结点,要么有且只有一个度为1的结点,而且此结点一定无右孩子;
完全二叉树由上至下,由左往右对结点进行依次编号(i=1时为根结点)
1)当i>1时,其双亲结点的值为(i/2)
2)2*i<=N时,其左孩子编号为2i,否则无左孩子
3)2*i+1<=N时,其左孩子编号为2*i,右孩子编号为2*i+1,否则无右孩子;
二叉树的四种遍历方式(先序、中序、后序、层次)
先序遍历:根->左->右;中序遍历:左->根->右;中序遍历:左->右->根;层次遍历:由上到下,由左到右;
已知中序和其他的任意一种遍历方式既可以唯一确定一颗二叉树;
二叉树的前三种遍历方式满足递归定义,通过递归可以实现(借助栈结构),层次遍历需要借助队列实现;
二叉树的存取方式(顺序存储、链式存储):顺序存取需要开辟一连续内存空间,会有空间上的浪费;对于链式存取
设立左右指针域,标明左右子树关系;
线索二叉树(充分利用空指针域来表明遍历的前驱和后继)方便直接找到遍历前驱与后继,加快查找速度
ltag | lchild | data | rchild | rtag |
根据遍历的顺序确定当前结点的前驱和后继;(左前驱,右后继)
ltag=0时,表示该结点有左孩子,左指针域指向左孩子结点;
ltag=1时,表示该结点无左孩子,左指针域指向此结点的前驱结点;
rtag=0时,表示该结点有右孩子,右指针域指向右孩子结点;
rtag=1时,表示该结点无右孩子,左指针域指向此结点的后继结点;
总结:0表示该结点有对应的孩子,1表示该结点指针域为NULL,指向其前驱和后继;
树的表示方法:双亲表示法、孩子表示法、孩子兄弟法(左孩子右兄弟)根结点的右指针域为NULL;
☆☆☆树与森林的转化:
任何一颗和树对应的二叉树其根结点的右子树必定为空NULL。(左孩子,右兄弟)
(森林和二叉树可以相互转化)
森林转化成二叉树:
F={T1,T2,....}为一森林集合
如果F为NULL,则次此二叉树为空树;
如果F不为空,二叉树的根即为集合中T1的根,二叉树的左子树是T1根结点的子树森林中转化而成的二叉树,
二叉树的右子树为原集合中剩余部分所转化成的二叉树。
1、将所有树先转化成二叉树;
2、后一个二叉树作为前一个二叉树的右孩子,第一个二叉树为根。
树转化成二叉树:
1、连接具有相同双亲的兄弟结点
2、除了第一个孩子结点之外,删除剩余兄弟结点与双亲的连线。
3、剩余部分即为生成的二叉树。
二叉树转化成树:
1、加线:若某结点的左孩子结点存在,则将这个左孩子的右孩子结点、右孩子的右孩子结点、右孩子的右孩子的右孩子结点…,
都作为结点的孩子。将结点与这些右孩子结点用线连接起来。
2、去线:删除原二叉树中所有结点与其右孩子结点的连线。
3、层次调整。
二叉树转化成森林:
B={root,LB,RB}
如果二叉树为空:则森林为空
如果二叉树不为空,则森林中第一颗树的根为二叉树的根root,T1中根结点的子树森林F1是由二叉树左子树LB转化
而成的森林;F中除了T1之外的其余树组成的森林F'={T2,T3,...}是由二叉树B的右子树转化而来的。
1、断开从根结点沿着右下角路径上的所有连线。
2、将生成的二叉树变成森林即可。
树、二叉树、森林转化的总结:
1、树转化为二叉树:连接所有的兄弟结点,去除除了第一个结点之外的其他与父节点的连线,
以根为轴心顺时针旋转45度;
(二叉树转化为树与之相反)
2、森林转化为二叉树:将森林中的每一颗树转化成二叉树。
连接新生成二叉树的每一个根结点(第一颗树的根结点为生成二叉树的树根,有指针域指向第二颗子树,依次类推);
以根为旋转轴顺时针旋转45度;
3、二叉树转化为森林:断开从根结点开始一直向右下方的所有连线,生成多颗二叉子树,
将每颗二叉子树转化成树即可构成森林;
树、森林、二叉树的遍历之间的关系:
树 | 森林 | 二叉树 |
先根遍历 | 先序遍历 | 先序遍历 |
后根遍历 | 中序遍历 | 中序遍历 |
哈夫曼树(哈夫曼编码):左零右一,哈夫曼编码为最优前缀编码,叶子结点保存数据
前缀编码:任何一个编码都不是另一个编码的前缀则此编码称为前缀编码;
哈夫曼树为带权路径长度最小的树,其树形并不唯一,但所求权值一定相同;
☆☆☆哈夫曼树的构造:(左0右1)
1)有N个结点各自为根形成一个集合(森林)
2)从集合中选取最小的两个值作为叶子结点,生成一颗新树,此树根结点的权值为叶子结点的权值之和;
如果权值相同,优先选用高度最小的;将原树结点删除,将新生成的树加入集合(森林)中;
3)重复2步骤直到森林中只有一颗树,该树就为哈夫曼树;
二叉排序树(BST):要么为一颗空树,要么满足一下定义(递归定义)
1)左子树非空,则左子树中任意结点的值小于根节点的值;
2)右子树非空,则右子树中任意结点的值大于根结点的值;
3)左右子树又满足一颗二叉排序树的定义;
特点:中序遍历得到的是一个有序序列。对于二叉排序树的查找最优时间复杂度为O(log2n),最坏为单支树的情况O(n);
所以二叉排序树的查找效率与树形(高)有关;若本身插入的构造数据有序,则此二叉排序树为单支树;
二叉排序树的删除:1)如果是叶子结点则直接删除;(不影响二叉排序树的性质)
2)如果为非叶子结点且只有一颗左或右子树,则直接让子树的根结点代替原删除结点即可;
3)如果为非叶子结点且有左右子树,则让子树中的子女位置填充删除结点的位置;
比如右子树中最左侧的结点或者左子树中最右侧的结点;
平衡二叉树:
定义:要么为空树,要么满足一下定义;
每个结点的左右子树的深度之差(平衡因子)的绝对值不超过1;(平衡因子只能是-1,0,1)
☆☆☆重点:对于平衡二叉树的调整:(左逆右顺,负负得正)
LL型:在A结点左子树根结点的左子树插入结点,导致A结点平衡因子由1变2
进行一次顺时针旋转;将原根结点的左孩子作为新生成树的根结点,将左孩子的右子树作为原树根结点的左孩子。
RR型:在A结点右子树根结点的右子树插入结点,导致A结点平衡因子由-1变-2
进行一次逆时针旋转;将原根结点的右孩子作为新生成树的根结点,将右孩子的左子树作为原树根结点的右孩子。
LR型:在A结点左子树根结点的右子树插入结点,导致A结点平衡因子由1变2
先逆时针旋转一次,后顺时针旋转一次;
将新插入的部分作为此插入结点父节点的右孩子,逆时针旋转一次,将此结点作为此子树的根结点,将其原父节点作为此 结点的左孩子,再将此结点的右孩子作为原树根结点的左孩子,顺时针旋转一次,将此结点作为整个树的根结点,将原根 结点作为新生成树的右孩子。
RL型:在A结点右子树根结点的左子树插入结点,导致A结点平衡因子由-1变-2
先顺时针旋转一次,后逆时针旋转一次;
将新插入的部分作为此插入结点父节点的左孩子,顺时针旋转一次,将此结点作为此子树的根结点,将其原父节点作为此 结点的右孩子,再将此结点的左孩子作为原树根结点的右孩子,逆时针旋转一次,将此结点作为整颗树的根结点,将原根 结点作为新生成树的左孩子。
高度为h的平衡二叉树结点的最小值问题:N1=1、N2=2、N3=4、N4=7
递推公式Nh=Nh-1+Nh-2+1;(前两项的值的和加1)