第五章 树和二叉树

             第五章 树和二叉树

一、树的逻辑结构

1.树的定义

  树是n个结点(数据元素)的有限集合;

  n=0时,空树;

  n=1时,只有根结点的树;

  n>1时,由一个根结点和若干互不相交的子树构成的树

2.树的逻辑关系

树是由一个根结点和若干子树构成,树中结点具有相同数据类型和层次关系

3.基本术语

  (1)叶子结点:度为0的结点,也称终端结点

  (2)分支结点:度不为0的结点,也称非终端结点

  (3)孩子/双亲/兄弟结点:某结点子树的根结点称为该结点的孩子结点;该结点称为其孩子结点的双亲结点;具有同一个双亲的孩子结点互称兄弟结点

  (4)路径:从双亲结点到孩子结点称为一条路径

  (5)森林:m棵互不相交的树的集合

    --------------------------------------------------------------------------

  (1)结点的度:某结点的子树个数

  (2)树的度:树中最大结点的度

  (3)结点的层数:根结点的层数为1

  (4)树的深度(高):树中最大结点的层数

  (5)路径长度:某路径上经过的边数

 

4.树的遍历

  (1)树的遍历是指从根结点出发,按照某种次序访问树中所有结点一次且仅一次

  (2)遍历方式(3种):前序遍历(先根);后序遍历(后根);层序遍历(逐层)

 



二、树的存储结构

1.双亲表示法

  (1)存储方式:用一维数组存储;

  (2)优点:方便求某结点的双亲和查找根结点等操作;

     缺点:不能反映各兄弟结点之间的关系;

2.孩子表示法

  (1)存储方式:用链表存储,有两种形式;

  形式1:多重链表表示法,

链表中每个结点包括一个数据域和多个指针域,每个指针域指向一个孩子结点

  形式2:孩子链表表示法,

    表头结点:包括结点的数据信息和该结点的孩子链表的头指针

    孩子结点:包括数据信息和指针域

    孩子链表:包括一个表头结点和该结点的所有孩子结点;

    孩子链表表示法是用多个孩子链表表示树,这些孩子链表的所有表头结点用数组存储,构成表头数组

  (2)优点:不仅表示了孩子结点的信息,而且链在同一个单链表中的结点具有兄弟关系

     缺点:查找双亲比较困难

3.双亲孩子表示法

  综合了双亲表示法和孩子链表表示法,在孩子链表的基础上,将表头结点内容设置为:“结点的数据信息 + 结点的双亲结点在数组中的下标 + 该结点的孩子链表的头指针”

4.孩子兄弟表示法(二叉链表表示法)

 

优点:便于实现树的各种操作

 



三、二叉树的逻辑结构

1.二叉树的定义

二叉树是n个结点(数据元素)的有限集合;

   n=0时,空二叉树;

    n=1时,只有根结点的二叉树;

    n=2时,根结点和左/右子树构成的二叉树

    n>2时,根结点和两棵互不相交的左、右子树构成的二叉树

 

2.二叉树的逻辑关系

二叉树是由一个根结点和两棵互不相交的左右子树构成,二叉树中结点具有相同数据类型和层次关系

3.特殊二叉树

  (1)斜树:所有结点都只有左子树的二叉树称为左斜树,所有结点都只有右子树的二叉树称为右斜树

     特点:斜树的结点个数与树的深度相同

  (2)满二叉树:所有分支结点都有左、右子树;所有叶子结点都在同层上

     特点:只有度为0和2的结点;叶子只能出现在最下一层

  (3)完全二叉树:按层序编号,未编满的二叉树

      特点:叶子结点只能出现在最下两层,且最下层的叶子结点都集中在二叉树左侧连续的位置;度为1的结点最多只会有一个,且该节点只有左孩子

4.二叉树的性质

   (1)二叉树的第i层上最多有个结点

   (2)深度为k的二叉树中,最多有个结点,最少有k个结点

   (3)0度结点比2度结点个数多1,

     --------------------完全二叉树的性质------------------

   (4)n个结点的完全二叉树的深度为

   (5)若双亲结点编号为i,则左孩子编号2i,右孩子编号2i+1

    若左孩子或者右孩子结点编号为i,则双亲结点编号为i/2

5.二叉树的遍历(4种)

  前序遍历;中序遍历;后序遍历;层序遍历

特点:已知二叉树的前序和中序序列或者中序和后序序列,都可唯一确定这棵二叉树

      但是已知前序和后序序列,不能唯一确定这棵二叉树

 

 


四、二叉树的存储结构

1.二叉树最常用的存储结构是二叉链表,此外还有三叉链表、线索表等

2.顺序存储结构

  (1)基本思想:增添一些并不存在的空结点,使一般的二叉树成为一棵完全二叉树,这样层序编号就可以唯一反映结点之间的逻辑关系,编号为i的结点存储到下标为i-1的位置

  (2)缺点:浪费存储空间,最坏情况是右斜树,深度为k的右斜树,只有k个结点,却要分配个存储单元

  (3)试用场合:二叉树的顺序存储结构是按层序存储的,一般仅适合存储完全二叉树

3.二叉链表

  (1)基本思想:另二叉树的每个结点对应一个链表结点,链表结点存放“二叉树结点数据信息+该结点的左孩子指针+该结点的右孩子指针”

(2)特点:在二叉链表中,若有n个结点,则有2n个指针域,其中只有n-1个指针域用来存储孩子结点的地址,剩余n+1个为空指针域

4.三叉链表 

          

5.线索链表

   (1)线索:利用二叉链表中的空指针域存放该结点在某种遍历序列中的前驱和后继结点的指针,这些前驱和后继结点的指针称为线索

  (2)线索二叉树:加上线索的二叉树称为线索二叉树

  (3)线索链表:加上线索的二叉链表称为线索链表

  (4)标志位: 为了区分某结点的指针域存放的是指向孩子的指针还是指向前驱或后继的线索,每个结点再增设两个标识位ltag和rtag

   (5)判断是否有左、右孩子,不能通过指针域是否为空来判断,要判断标志位是否为1

  例:线索二叉树结点R没有左孩子的充要条件:R.ltag=1

 


 

 



五、二叉树的应用:哈夫曼树及编码

1.叶子结点的权值

是对叶子结点赋予的一个有意义的数值量

2.二叉树的带权路径长度

         

3.哈夫曼树

带权路径长度最小的二叉树(最优二叉树)

  哈夫曼树的特点:

    (1)对给定的n个权值构造的哈夫曼树中,有n个叶子结点,n-1个分支结点

        (2)哈夫曼树可以不唯一,但它们具有相同的带权路径长度

  (3)哈夫曼树中不存在度为1的结点

4.前缀编码

如果在一组编码中任一编码都不是其他任何一个编码的前缀,这组编码称为前缀编码

5.哈夫曼编码

构造一棵哈夫曼编码树,规定哈夫曼编码树的左分支代表0,右分支代表1,则从根结点到每个叶子结点所经过的路径组成的0和1的序列便为该叶子结点对应字符的编码,称为哈夫曼编码

  哈夫曼编码的特点:

     (1)采用哈夫曼树构造的编码是一种能使字符串的编码总长度最短的不等长编码

        (2)哈夫曼编码是前缀编码

 




六、树、森林与二叉树的转换

1.讨论树、二叉树和森林的目的

   将树、森林按二叉树的存储方式进行存储,并利用二叉树的算法解决树的有关问题

2.树和二叉树的比较

   转换关系:两者之间具有一一对应的关系,可以相互转换,给定一棵树,可以找到唯一的二叉树与之对应

    相同处:从物理结构上看,树的孩子兄弟表示法和二叉树的二叉链表是相同的,只是解释不同

   不同处:(1)二叉树和树是两种树结构,二叉树不是度为2的树(左斜、右斜)

       (2)具有3个结点的树有2种形态,而具有3个结点的二叉树有5种形态

      

3.树转换为二叉树

  转换方法:

    (1)加线:树中所有相邻兄弟结点之间加一条连线;

    (2)去线:对树中的每个结点,只保留它与第一个孩子结点之间的连线,删去它与其他孩子结点之间的连线 

    (3)层次调整:以根结点为轴心,将树顺时针转动一定的角度,使之层次分明

  转换特点:

    (1)树中的父子关系变成二叉树中的左子树

       树中的兄弟关系变成二叉树中的右子树

    (2)由于树根结点无兄弟,所以转换的二叉树根结点无右子树

    (3)树的前序遍历对应二叉树的前序遍历

      树的后序遍历对应二叉树的中序遍历

4.森林转换为二叉树

  转换方法:

    (1)将森林中的每棵树转换成二叉树

    (2) 从第二棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树根结点的右孩子

  转换特点:

    (1)第一棵树的根结点作为二叉树的根结点,第一棵树的剩余结点作为二叉树的左子树,从第二棵树开始全部作为二叉树根结点的右子树

    (2)森林的前序遍历对应二叉树的前序遍历

     森林的后序遍历对应二叉树的中序遍历

5.二叉树转换为树或森林

   判定目标:若二叉树根结点无右子树,转换成树;若有,转换成森林 

   转换方法:

     (1)加线:若某结点x是其双亲y的左孩子,则把结点x的右孩子、右孩子的右孩子、……都与结点y连线

     (2)去线:删去原二叉树中所有的双亲结点与右孩子结点的连线

     (3)层次调整:整理由(1)、(2)两步所得到的树或森林,使之层次分明




附:计算题

1.一棵n个结点的满二叉树共有( )个叶子结点和( )个分支结点

2.高度为h的二叉树上只有0度和2度结点,该二叉树的结点数最多有( ),最少有()

3.具有100个结点的完全二叉树的叶子结点数为( 50 )

4.已知一棵度为3的树有2个1度结点,3个2度结点,4个3度结点,则该树中有(12 )个叶子结点

5.在具有n个结点的二叉链表中,共有(2n )个指针域,其中(n-1 )个指针域用于指向左右孩子没剩下的(n+1 )个指针域则是空的

6.在有n个叶子的哈夫曼树中,叶子结点总数为(n ),分支结点总数为(n-1 )

7.n个结点的二叉树深度最少为( ),最多为(n )

8.深度为k的完全二叉树至少有( )个结点,至多有( )个结点

9.设森林中有4棵树,树中结点的个数依次为n1,n2,n3,n4,则把森林转换成二叉树后,其根结点的右子树上有(n2+n3+n4)个结点,左子树上有(n1-1)个结点

10.为5个使用频率不等的字符设计哈夫曼编码,不可能的方案是( D )

     A.000,001,010,011,1             B.0000,0001,001,01,1

     C.000,001,01,10,11             D.00,100,101,111

11.已知完全二叉树的第8层有8个结点,则其叶结点数是( 68 )

12.前序序列为A,B,C且后序序列为C,B,A的二叉树共有(4 )种

13.3个结点可以组成(2 )种不同形态的树,(4 )种不同形态的二叉树

14.将一棵有100个结点的完全二叉树从上到下,从左到右依次结点编号,根结点的编号为1,则编号为45的结点的左孩子编号为(47 )

15.用5个权值{3,2,4,5,1}构造的哈弗曼树的带权路径长度为(33 )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
5.1 数的逻辑结构 5.1.1 1、的定义 在中常常将数据元素称为结点 (1)有且仅有一个特定的称为根的结点; (2)当n>1时,除根结点之外的其余结点被分成m(m>0)个互不相交的有限集合T1,T2,•••Tm,其中每个集合又是一棵树,并称为这个节点的子。 2、的基本术语: 结点 叶子节点、分支结点 孩子节点、分支结点、兄弟节点 路径、路径长 祖先、子孙 结点的层数、的深(高) 层序编号 有序、无序 森林 5.1.2 的抽象数据类型定义 5.1.3遍历操作 1、前序遍历 的前序遍历操作定义为: 若为空,则空操作返回;否则 (1)访问根结点 (2)按照从左向右的顺序前序遍历结点的每一棵子。 2、中序遍历 的中序遍历操作定义为: 若为空,则空操作返回;否则 (1)按照从左向右的顺序后序遍历结点的每一棵子; (2)访问根结点。 3、层序遍历 的层序遍历也称作的广泛遍历,其操作定义为的第一层开始,自上而下逐层遍历,在同一层中,按从左向右的顺序对结点逐个访问。 5.2的存储结构 5.2.1 双亲表示法 由的定义可知,中每个结点都有且仅有一个双亲结点。所以利用这一特性,可以用一维数组来存储各个结点,数组中一个元素对应一个结点,数组元素包括结点的数据信息以及该结点的双亲在数组中的下标。 其中: Data为数据域,存储结点的数据信息; Parent为指针即游标,存储该结点的双亲在数组中的小标。 5.2.2孩子表示法 1、多重链表表示法 (1)指针域的个数等于该结点。 (2)指针域的个数等于。 2、孩子链表表示法 把孩子看成一个线性表,且以单链表存储,称为该结点的孩子链表。则n个结点有n个孩子链表。 孩子节点有两类:孩子节点、表头结点。 5.2.3 双亲孩子表示法 即将双亲表示法和孩子链表表示法相结合的存储方法。仍将各结点的孩子分别组成单链表,同时用一维数组顺序存储中的各结点,数组元素除了包括结点的数据信息和该结点的孩子链表的头指针之外,还增设一个域存储该结点的双亲在数组的下标。 5.2.4孩子兄弟表示法 又称二链表表示法,其方法是链表中每个结点除数据域外,还设置了两个指针分别指向该结点的第一个孩子和右兄弟链表的结构: Firstchild data rightsib 指针域,存储第一个孩子结点的存储地址 数据域,存储该结点的数据信息 指针域,存储该结点右兄弟结点的存储地址 5.3二叉树的逻辑结构 最简单的结构,特别适合计算机处理,而且任何数都可以简单的转换为二叉树。(重点内容) 5.3.1二叉树的定义 二叉树是n(n>=0)个结点的有限集合,该集合或者为空集,或者有一个根节点和两棵互不相交的、分别称为根节点的左子和右子二叉树组成。 二叉树具有五种基本形态: 1、空二叉树; 2、只有一个根结点; 3、根结点只有左子; 4、根结点只有右子; 5、根结点既有左子又有右子 特殊二叉树: 1、斜; 2、满二叉树; 3、完全二叉树; 5.3.2二叉树的基本性质 性质5-1 二叉树的第i层上最多有2^(i-1)个结点(i>=1)。 性质5-2 在一棵深为k的二叉树中,最多有2^k-1个结点,最少有k个结点。 性质5-3 在一棵二叉树中,如果叶子结点的个数为n0,为2的结点个数为n2,则n0=n2+1. 性质5-4 具有n个结点的完全二叉树的深为【log2^n】+1。 性质5-5 对一棵具有n个结点的完全二叉树中的结点从一开始按层序编号,则对于任意的编号为i(1<=i<=n)的结点,有: (1)如果i>1,则结点i的双亲的编号为【i/2】;否则结点i是根结点,无双亲。 (2)如果2i<=n,则 结点i的左孩子的编号为2i;否则结点i无左孩子。 (3)如果2i+1<=n,则结点i的右孩子的编号为2i+1,否则结点i无右孩子。 5.3.3 二叉树的抽象数据类型定义 同类似,在不同的应用中,二叉树的基本操作不尽相同。 5.3.4 二叉树遍历操作 二叉树遍历是指从根节点出发,按照某种次序访问二叉树是所有结点,使得每个结点被访问一次且仅被访问一次。由于二叉树中每个结点都可能有两个子,因此需要寻找一条合适的搜索路径。 1、前序遍历 前序遍历二叉树操作定义为: 若为空,则空操作返回;否则 (1)访问根结点 (2)前序遍历结点的左子 (3)前序遍历结点的右子 2、中序遍历 中序遍历二叉树操作定义为: 若为空,则空操作返回;否则 (1)中序遍历结点的左子 (2)访问根结点 (3)中序遍历结点的右子 3、后序遍历 后序遍历结点的左子 后序遍历结点的右子 访问根结点 4、层序遍历 二叉树的层序遍历是指从二叉树的第一层开始,从上之下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。 5.4 二叉树存储结构及实现 5.4.1 顺序存储结构 具体步骤: (1)将二叉树按完全二叉树编号。 (2)将二叉树中的结点一编号顺序存储到一维数组中。 5.4.2 二叉链表 基本思想: 令二叉树的每个结点对应一个链表结点,链表结点除了存放于二叉树结点有关的数据信息外,还要设置指示左右孩子的指针。 5.4.3 三叉链表 在二叉链表存储方式下,从某个结点出发可以直接访问它的孩子结点,但要找到它的双亲结点,则需要从根节点开始搜索,最坏的情况下,需要遍历整个二叉链表。此时采用三叉链表储存二叉树。 其中,data,lchild,rchild三个域的含义同二叉树,parent域为指向该结点的双亲结点指针。 5.4.4 线索链表 按照某种遍历次序对二叉树进行遍历,可以把二叉树中所有结点排成一个线性序列。在集体应用中,有时需要访问二叉树中的结点在某种遍历序列中前驱和后继,此时,在存储结构中应该保存结点在某种遍历序列中的前驱和后继信息。 前驱和后继结点的指针称为线索,加上线索的二叉树称为线索二叉树,加上线索的二叉链表称为线索链表。 5.5 二叉树遍历的非递归算法 5.5.1 前序遍历非递归算法 关键:在前序遍历过某个左子后,如何找到该结点的右子的根指针。 一般的前序遍历执行过程中,设要遍历二叉树的根指针为bt,可能出现两种情况: (1)若bt!=NULL,则表明当前二叉树不为空,此时,应输入根结点bt的值并将bt保存到栈中,准备继续遍历bt的左子。 (2)若bt=NULL,则表明以bt为根指针的二叉树遍历完毕,并且bt是栈顶指针所指结点的左子,若栈不空,则应根据栈顶指针所指结点找到待遍历右子的根指针并赋予bt,以继续遍历下去;若栈空,则表明整个二叉树遍历完毕。 5.5.2 中序遍历非递归算法算法只是需要将前序遍历的非递归算法中输出的语句cout<<bt->data移到bt=s[top--]之后即可。 5.5.3 后序遍历非递归算法 后序遍历的不同在于:结点要出入两次栈,出两次栈,这种情况的含义和处理方法为: (1)第一次出栈:只遍历晚左子,右子尚未遍历,则该结点不出栈,利用栈顶结点找到它的右子,准备遍历它的右子。 (2)第二次出栈:遍历完右子,该结点出栈,并访问它。 设根指针为bt,则可能有以下两种情况: (1)若bt!=NULL,则bt及标志flag入栈,遍历其左子。 (2)若bt=NULL,此时栈空,则整个遍历结束;若栈不空,则表明栈顶结点的左子或右子遍历结束。若栈顶点的标志flag=1,则表明栈结点的左子遍历完毕,将flag修改为2,修改为2,并遍历栈定点的右子;若栈顶结点的标志flag=2,则表明栈结点的右子遍历完毕,输出栈顶结点。 5.6 、森林与二叉树的转换 1.转换为二叉树一棵树转换为二叉树的方法为: (1)加线——中所有相邻的兄弟结点之间加一条线; (2)去线——对中的每个节点,只保留它与第一个孩子结点之间的连线,删去它与其他孩子结点之间的连线。 (3)层次调节——以根结点为轴心,将顺时针转动一定角,使之层次分明。 2.森林转换成二叉树 (1)将森林中的每一棵二叉树转化成二叉树; (2)从第二课二叉树开始,依次把后一棵二叉树的根结点作为一棵二叉树根节点的右孩子,当所有二叉树连起来后,此时所得到的二叉树就是由森林转换得到的二叉树。 3、二叉树转换为或森林 (1)加线——若某个结点x是其双亲y的左孩子,则把结点x的右孩子、右孩子的右孩子、……,都与结点y用线连起来; (2)去线——删去原二叉树中所有的双亲结点与右孩子结点的连线; (3)层次调整——整理由(1)、(2)两步所得到的或森林,使之层次分明。 (4)森林的遍历 两种遍历方法;前序遍历后续遍历。 5.7 应用举例 5.7.1 二叉树的应用举例——哈夫曼及哈夫曼编码 1、哈夫曼也称最优二叉树,在实际中有着广泛的应用。 叶子节点的权值 是对叶子结点赋予的一个有意义的数值量。 二叉树的带权路径长二叉树具有n个带权值的叶子节点,从根节点到叶子节点的路径长与相应的叶子节点权值的乘积之和叫做二叉树的带权路径长,记为: WPL=EWkLk 哈夫曼 给定一组具有确定权值的叶子结点,可以构造出不同的二叉树,将其中带权值路径长最小的二叉树称为哈夫曼。 哈夫曼算法基本思想: (1)初始化:由给定的n个权值构造n棵只有一个根结点二叉树,从而得到一个二叉树集合。 (2)选取与合并:在F中选取根结点的权值最小的两棵二叉树分别作为左、右子构造一棵新的二叉树,这棵新的二叉树的根结点的权值为其左右子结点的权值之和。 (3)删除与加入:在F中删除作为左、右子的两棵二叉树,并将新建的二叉树加入到F中。 (4)重复(2)(3)两步的操作,当集合F只剩下一棵二叉树时这棵二叉树便是哈夫曼。 2、哈夫曼编码 在进行程序设计时,通常给每一个字符记一个单独的代码来表示一组字符,我们称之为编码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值