数据结构树和森林

知识要点:

树的结构和主要概念,各种二叉树的结构及其特点;

二叉树的三种遍历方法的实现原理和性质,能将二叉树的遍历方法应用于求解二叉树的叶子结点个数、二叉树计数等问题,遍历的非递归实现方法;

线索化二叉树的结构和基本操作;(充分利用二叉树的空链域)

森林的定义和存储结构,森林的遍历等方法的实现;(遍历方式与二叉树一致)

基于霍夫曼树生成霍夫曼编码的方法;

最优二叉树(霍夫曼树)的构造原理和相关算法。

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)

           logm[n(m-1)+1]<=h

二叉树的定义:(递归定义且为有序树子树之间不能相互变化)

要么为空树,要么满足以下定义:

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)

 

 

 

你可能感兴趣的:(数据结构)