数据结构树和二叉树

整本书的知识点,点击右方链接整本书笔记知识点

 

 

五、树和二叉树

5.1、树和二叉树的定义

5.1.1、树的定义

  1. 树是一种非线性的数据结构,它是由n个有限结点组成有层次关系的集合.

  2. 树具有以下特点,可以根据这些特点来判断一个数据结构是否是树

    •每个结点具有0个或多个子结点
    •每个子结点只有一个父结点
    •没有前驱的结为根结点
    •除了根结点外,每个子结点又可以由m棵不相关的子树组成

在这里插入图片描述

每个结点最多有一个父结点

在这里插入图片描述

5.1.2、树的基本术语

  1. 结点的度:结点拥有的子树数量称为结点的度

在这里插入图片描述

  1. 树的度:树内各结点度的最大值,即上图 D 结点的度就是此树的度

  2. 叶子:度为 0 的节点称为叶子或终端节点

  3. 结点的层次和树的深度

在这里插入图片描述

  1. 森林:m棵互不相交的树的集合。

5.1.3、二叉树的定义

二叉树与数主要有以下区别:

  1. 二叉树每个结点至多只有两颗子树(即二叉树中不能存在度大于 2 的结点)
  2. 二叉树的子树有左右之分,其次序不能任意颠倒
  3. 即使树中某结点只有一棵子树,也要区分它是左子树还是右子树

在这里插入图片描述

5.2、案例引入

5.3、树和二叉树的抽象数据类型定义

数据对象集:一个有穷的结点集合。
若不为空,则由根结点和其左、右二叉子树组成。
操作集: BT ∈ BinTree, Item ∈ElementType,重要操作有:
Boolean IsEmpty( BinTree BT ): 判别BT是否为空;
void Traversal( BinTree BT ):遍历,按某顺序访问每个结点;
BinTree CreatBinTree( ):创建一个二叉树。

常用的遍历方法有:

  • void PreOrderTraversal( BinTree BT ):先序----根、左子树、右子树;
  • void InOrderTraversal( BinTree BT ): 中序—左子树、根、右子树;
  • void PostOrderTraversal( BinTree BT ):后序—左子树、右子树、根
  • void LevelOrderTraversal( BinTree BT ):层次遍历,从上到下、从左到右

5.4、二叉树的性质和存储结构

5.4.1、二叉树的性质

在这里插入图片描述

性质1:在二叉树的第i层上至多有2i-1个结点(i>=1)

性质2:深度为k的二叉树至多有2k-1个结点(k>=1)

性质3:对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0 = n2+1

一棵二叉树,除了终端结点(叶子结点),就是度为1或2的结点。假设n1表示度为1的结点数,则树 T 的结点总数

n=n0+n1+n2 ,我们再换个角度,看一下树T的连接线数,除了根节点,其他结点都有一根线表示分支进入,所以连接线数为结点总数减去1。按连接线树算的话:n-1=n1+2n2,可推导出n0+n1+n2-1 = n1+2n2,继续推导可得n0 = n2+1

满二叉树:深度为 k 且含有 2k-1个结点

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

性质4:具有n个结点的完全二叉树的深度为[log2n ] + 1

性质5:如果对一颗有n个结点的完全二叉树(其深度为[log2n ] + 1)的结点按层序编号(从第1层到第[log2n ] + 1层,每层从左到右),对任一结点i(1<=i<=n)有:

  1. 如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是结点 [i/2]

  2. 如果2i>n,则结点 i 无孩子(结点i为叶子结点);否则其左孩子是结点 2i

  3. 如果2i+1>n,则结点 i 无右孩子;否则其右孩子是结点 2i+1

在这里插入图片描述

5.4.2、二叉树的存储结构

①、顺序存储结构

在这里插入图片描述

二叉树的顺序存储结构缺点很明显:不能反应逻辑关系;对于特殊的二叉树(左斜树、右斜树),浪费存储空间。所以二叉树顺序存储结构一般只用于完全二叉树。

②、链式存储结构

在这里插入图片描述

	//二叉树的二叉链表存储表示
    typedef struct BiTNode {
        TElemType data;                     //结点数据域
        struct BiTNode *lchild, *rlchild;   //左右孩子指针
    } BiTNode, *BiTree;

5.5、遍历二叉树和线索二叉树

5.5.1、遍历二叉树

二叉树的遍历是指从根结点出发,按照某种次序访问二叉树中的所有结点,使得每个结点被访问一次且仅被访问一次

在这里插入图片描述

如果限定先左后右,则二叉树遍历方式有三种: 先序(根):DLR; 中序(根):LDR ;后序(根):LRD

在这里插入图片描述

中序遍历的递归算法:在这里插入图片描述

中序遍历的非递归算法:在这里插入图片描述

在这里插入图片描述

 

根据遍历序列确定二叉树

在这里插入图片描述

根据前序可知 A 为根节点,再看中序可知 BC 是在根节点 A 左子树,EDGHFI 是在根节点 A 右子树

再看前序和中序可知,B 为 根节点 A 的左孩子,C为B的右孩子,由此类推。

已知一棵二叉树的后序序列和中序序列,分别是DECBHGFA 和BDCEAFHG 是否可以唯一确定这棵树?

①由后序遍历特征,根结点必在后序序列尾部(即A);

②由中序遍历特征,根结点必在其中间,而且其左部必全部是左子树子孙(即BDCE),其右部必全部是右子树子孙(即FHG);

③继而,根据后序中的DECB子树可确定B为A的左孩子,根据HGF子串可确定F为A的右孩子;

二叉树遍历算法的应用
在这里插入图片描述

在这里插入图片描述

5.5.2、线索二叉树

在这里插入图片描述

对于n个结点的二叉树,则在二叉链存储结构中就会有n+1个空链域

对于一个有 n 个结点的二叉链表,每个结点指向左右孩子的两个指针域,故共有 2n 个指针域,而 n 个结点的二叉树共有 n-1 条分支,即存在 2n-(n-1) = n+1 个空链域

如果一个结点的左孩子为空,则指向它的前驱结点。

如果一个结点右孩子为空,则指向它的后继。

怎么理解这句话,我们来看一个例子

在这里插入图片描述

它的后序遍历为: DBEFCA

那么它的后序线索二叉树是怎么画的呢?

我们根据它的后序遍历的结果来画后序线索二叉树

先来看D: D的左孩子为空,则指向它的前驱,它没有前驱。
D的右孩子为空,则指向它的后继,也就是B。

在这里插入图片描述

再来看B:B的左孩子为空,则指向它的前驱,它的前驱根据后序遍历的结果是D,所以B的左孩子指向D
B的右孩子不为空

在这里插入图片描述

再来看E,E的左孩子为空,则指向它的前驱结点B,E的右孩子为空,则指向它的后继结点F

在这里插入图片描述

再来看F,它的左孩子为空,则指向它的前驱结点E。它的右孩子为空,则指向它的后继节点C

在这里插入图片描述

线索二叉树的结点形式:在这里插入图片描述

LTag是在 lchild 不存储指针的时候才有其作用,说到底,是利用那 n-1 个空链域存储LTag和RTag,并没有开辟新的内存空间用来存储前驱和后继

在这里插入图片描述

和双向链表结点一样,在二叉树链表上添加一个头结点,如下图所示,并令其lchild域的指针指向二叉树的根结点(图中第一步),其rchild域的指针指向中序遍历访问时的最后一个结点(图中第二步)。反之,令二叉树的中序序列中第一个结点中,lchild域指针和最后一个结点的rchild域指针均指向头结点(图中第三和第四步)。这样的好处是:我们既可以从第一个结点起顺后继进行遍历,也可以从最后一个结点起顺前驱进行遍历。

在这里插入图片描述

在这里插入图片描述

线索二叉树的遍历和构造伪码点超链接

线索二叉树的遍历和构造伪码

5.6、树和森林

5.6.1、树的存储结构

双亲表示法

在这里插入图片描述
 
孩子表示法


 

孩子兄弟表示法(常用)

在这里插入图片描述

5.6.2、森林与二叉树的转换

在这里插入图片描述

(1)转换:把每棵树转换为二叉树。(即根结点没有右孩子的二叉树)
在这里插入图片描述

(2)连接:第一棵二叉树不动,从第二棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树的根结点的右孩子,用线连接起来。
在这里插入图片描述

(3)旋转

在这里插入图片描述

二叉树转换为森林


在这里插入图片描述

(1)逆旋转

在这里插入图片描述

(2)抹线:从根结点开始,依次抹掉结点与右孩子的连线,直到结点没有右孩子为止

在这里插入图片描述

(3)转换:将二叉树转换成树(也可以省略该步骤)

在这里插入图片描述

5.6.3、树和森林的遍历

1、树的遍历前面写了

2、森林的遍历

先序遍历森林。

  • 若森林非空,访问森林的第一棵树的根结点。
  • 先序遍历第一棵树中根结点的子树
  • 先序遍历除去掉遍历过的树的森林

中序遍历森林:普通的树构成的森林是不存在中序遍历的,这里的中序遍历必然指代的是化成二叉树的森林。

后序遍历也可以相似定义

5.7、哈弗曼树及其应用

5.7.1、哈弗曼树的基本概念

哈弗曼树又被称为最优树

​ 路径:从一个结点到另一个结点之间的分支序列

​ 路径长度:从一个结点到另一个结点所经过的分支数目

​ 结点的权:根据应用的需要可以给树的结点赋权值

​ 带权路径长度:从根到该结点的路径长度与该结点权的乘积

​ 树的带权路径长度:树中所有叶子结点的带权路径之和

​ 哈夫曼树:由n个带权叶子结点构成的所有二叉树中带权路径长度最短的二叉树

哈弗曼树不存在度为 1 的结点。
n个叶子结点的哈弗曼树有 2n-1 个结点

在构造哈弗曼树时,是从叶子结点向根节点的方向进行的,每次都是两个两个成对的结点来形成一个新的分支结点,所以不存在度为1的结点。

在这里插入图片描述

其中第三个树的WPL最小,根据验证,其为哈弗曼树。

5.7.2、哈夫曼树的构造算法

  1. 初始化:根据给定的n个权值 ,构造n棵只有一个根结点的二叉树, 这n棵二叉树构成森林F
  2. 找最小树:在F中选取两棵根结点树值最小的树作为左、右子树,构造一颗新的二叉树,置新二叉树根的权值为左、右子树根结点权值之和;
  3. 删除与加入:从F中删除这两颗树,并将新树加入F;
  4. 判断:重复 2)和 3),直到F中只含一颗树为止,此时得到的这颗二叉树就是哈夫曼树。

示例:w={5,29, 7, 8, 14, 23, 3, 11}

在这里插入图片描述

5.7.3、哈夫曼编码

前缀码:如果在一个编码系统中,任一个编码都不是其他任何编码的前缀,则称该编码系统中的编码是前缀码。例如,一组编码01,001,010,100,110就不是前缀码,因为01是010的前缀,若去掉01或010就是前缀码。

哈夫曼编码:对一棵具有n个叶子的哈夫曼树,若对树中的每个左分支赋予0,右分支赋予1,则从根到每个叶子的通路上,各分支的赋值分别构成一个二进制串,该二进制串就称为哈夫曼编码。

哈夫曼编码是最优前缀码

在这里插入图片描述

二叉树案例

二叉树案例

第五章小结

在这里插入图片描述

  1. 二叉树是一种最常用的树形结构,二叉树具有一些特殊的性质, 而满二叉树和完全二叉树又是两种特殊形态的二叉树。
  2. 二叉树有两种存储表示:顺序存储和链式存储。顺序存储就是把二叉树的所有结点按照层次
  3. 顺序存储到连续的存储单元中,这种存储更适用于完全二叉树。链式存储又称二叉链表,每个结点包括两个指针,分别指向其左孩子和右孩子。链式存储是二叉树常用的存储结构。
  4. 树的存储结构有三种:双亲表示法、孩子表示法和孩子兄弟表示法,孩子兄弟表示法是常用的表示法,任意一棵树都能通过孩子兄弟表示法转换为二叉树进行存储。森林与二叉树之间也存在相应的转换方法,通过这些转换,可以利用二叉树的操作解决一般树的有关问题。
  5. 在线索二叉树中,利用二叉链表中的 n+1 个空指针域来存放指向某种遍历次序下的前驱结点和后继结点的指针,这些附加的指针就称为 "线索"。引入二叉线索树的目的是加快查找结点前驱或后继的速度。
  6. 哈夫曼树在通信编码技术上有广泛的应用,只要构造了哈夫曼树,按分支情况在左路径上写代码0, 右路径上写代码1,然后从上到下叶结点相应路径上的代码序列就是该叶结点的最优前缀码, 即哈夫曼编码。

第五章习题

(1)把一棵树转换为二叉树后,这棵二叉树的形态是( )。

A.唯一的 B.有多种

C.有多种,但根结点都没有左孩子 D.有多种,但根结点都没有右孩子

答案:A

解释:因为二叉树有左孩子、右孩子之分,故一棵树转换为二叉树后,这棵二叉树的形态是唯一的。

(2)由3个结点可以构造出多少种不同的二叉树?( )

A.2 B.3 C.4 D.5

答案:D

解释:五种情况如下:在这里插入图片描述

(3)一棵完全二叉树上有1001个结点,其中叶子结点的个数是( )。

A.250 B. 500 C.254 D.501

答案:D

解释:设度为0结点(叶子结点)个数为A,度为1的结点个数为B,度为2的结点个数为C,有A=C+1,A+B+C=1001,可得2C+B=1000,由完全二叉树的性质可得B=0或1,又因为C为整数,所以B=0,C=500,A=501,即有501个叶子结点。

(4)一个具有1025个结点的二叉树的高h为( )。

A.11 B.10 C.11至1025之间 D.10至1024之间

答案:C

解释:若每层仅有一个结点,则树高h为1025;且其最小树高为[ log21025] + 1=11,即h在11至1025之间。

(5)深度为h的满m叉树的第k层有( )个结点。(1=<k=<h)

A.mk-1 B.mk-1 C.mh-1 D.mh-1

答案:A

解释:深度为h的满m叉树共有mh-1个结点,第k层有mk-1个结点。

(6)利用二叉链表存储树,则根结点的右指针是( )。

A.指向最左孩子 B.指向最右孩子 C.空 D.非空

答案:C

解释:利用二叉链表存储树时,右指针指向兄弟结点,因为根节点没有兄弟结点,故根节点的右指针指向空。

(7)对二叉树的结点从1开始进行连续编号,要求每个结点的编号大于其左、右孩子的编号,同一结点的左右孩子中,其左孩子的编号小于其右孩子的编号,可采用( )遍历实现编号。

A.先序 B. 中序 C. 后序 D. 从根开始按层次遍历

答案:C

解释:根据题意可知按照先左孩子、再右孩子、最后双亲结点的顺序遍历二叉树,即后序遍历二叉树。

(8)若二叉树采用二叉链表存储结构,要交换其所有分支结点左、右子树的位置,利用( )遍历方法最合适。

A.前序 B.中序 C.后序 D.按层次

答案:C

解释:后续遍历和层次遍历均可实现左右子树的交换,不过层次遍历的实现消耗比后续大,后序遍历方法最合适。

(9)在下列存储形式中,( )不是树的存储形式?

A.双亲表示法 B.孩子表示法 C.孩子兄弟表示法 D.顺序存储表示法

答案:D

解释:树的存储结构有三种:双亲表示法、孩子表示法、孩子兄弟表示法,其中孩子兄弟表示法是常用的表示法,任意一棵树都能通过孩子兄弟表示法转换为二叉树进行存储。

(10)一棵非空的二叉树的先序遍历序列与后序遍历序列正好相反,则该二叉树一定满足( )。

A.所有的结点均无左孩子 B.所有的结点均无右孩子

C.只有一个叶子结点 D.是任意一棵二叉树

答案:C

解释:因为先序遍历结果是“中左右”,后序遍历结果是“左右中”,当没有左子树时,就是“中右”和“右中”;当没有右子树时,就是“中左”和“左中”。则所有的结点均无左孩子或所有的结点均无右孩子均可,所以A、B不能选,又所有的结点均无左孩子与所有的结点均无右孩子时,均只有一个叶子结点,故选C。

(11)设哈夫曼树中有199个结点,则该哈夫曼树中有( )个叶子结点。

A.99 B.100

C.101 D.102

答案:B

解释:在哈夫曼树中没有度为1的结点,只有度为0(叶子结点)和度为2的结点。设叶子结点的个数为n0,度为2的结点的个数为n2,由二叉树的性质n0=n2+1,则总结点数n= n0+n2=2*n0-1,得到n0=100。

(12)若X是二叉中序线索树中一个有左孩子的结点,且X不为根,则X的前驱为( )。

A.X的双亲 B.X的右子树中最左的结点

C.X的左子树中最右结点 D.X的左子树中最右叶结点

答案:C

(13)引入二叉线索树的目的是( )。

A.加快查找结点的前驱或后继的速度 B.为了能在二叉树中方便的进行插入与删除

C.为了能方便的找到双亲 D.使二叉树的遍历结果唯一

答案:A

(14)设F是一个森林,B是由F变换得的二叉树。若F中有n个非终端结点,则B中右指针域为空的结点有( )个。

A.n−1 B.n C.n + 1 D.n + 2

答案:C

(15)n(n≥2)个权值均不相同的字符构成哈夫曼树,关于该树的叙述中,错误的是( )。

A.该树一定是一棵完全二叉树

B.树中一定没有度为1的结点

C.树中两个权值最小的结点一定是兄弟结点

D.树中任一非叶结点的权值一定不小于下一层任一结点的权值

答案:A

解释:哈夫曼树的构造过程是每次都选取权值最小的树作为左右子树构造一棵新的二叉树,所以树中一定没有度为1的结点、两个权值最小的结点一定是兄弟结点、任一非叶结点的权值一定不小于下一层任一结点的权值。

  • 102
    点赞
  • 261
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
数据结构》(C语言版)是为“数据结构”课程编写的教材,也可作为学习数据结构及其算法的C程序设计的参教材。学了数据结构后,许多以前写起来很繁杂的代码现在写起来很清晰明了. 本书的前半部分从抽象据类型的角度讨论各种基本类型的数据结构及其应用;后半部分主要讨论查找和排序的各种实现方法及其综合分析比较。 全书采用类C语言作为数据结构和算法的描述语言。 本书概念表述严谨,逻辑推理严密,语言精炼,用词达意,并有配套出版的《数据结构题集》(C语言版),便于教学,又便于自学。 本书后附有光盘。光盘内容可在DOS环境下运行的以类C语言描述的“数据结构算法动态模拟辅助教学软件,以及在Windows环境下运行的以类PASCAL或类C两种语言描述的“数据结构算法动态模拟辅助教学软件”。内附 数据结构算法实现(严蔚敏版配套实现程序) 目录: 第1章 绪论 1.1 什么是数据结构 1.2 基本概念和术语 1.3 抽象据类型的表现与实现 1.4 算法和算法分析 第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示及相加 第3章 栈和队列 3.1 栈 3.2 栈的应有和举例 3.3 栈与递归的实现 3.4 队列 3.5 离散事件模拟 第4章 串 4.1 串类型的定义 4.2 串的表示和实现 4.3 串的模式匹配算法 4.4 串操作应用举例 第5章 组和广义表 5.1 组的定义 5.2 组的顺序表现和实现 5.3 矩阵的压缩存储 5.4 广义表的定义 5.5 广义表的储存结构 5.6 m元多项式的表示 5.7 广义表的递归算法第6章 二叉树 6.1 的定义和基本术语 6.2 二叉树 6.2.1 二叉树的定义 6.2.2 二叉树的性质 6.2.3 二叉树的存储结构 6.3 遍历二叉树和线索二叉树 6.3.1 遍历二叉树 6.3.2 线索二叉树 6.4 和森林 6.4.1 的存储结构 6.4.2 森林与二叉树的转换 6.4.3 和森林的遍历 6.5 与等价问题 6.6 赫夫曼及其应用 6.6.1 最优二叉树(赫夫曼) 6.6.2 赫夫曼编码 6.7 回溯法与的遍历 6.8 的计 第7章 图 7.1 图的定义和术语 7.2 图的存储结构 7.2.1 组表示法 7.2.2 邻接表 7.2.3 十字链表 7.2.4 邻接多重表 7.3 图的遍历 7.3.1 深度优先搜索 7.3.2 广度优先搜索 7.4 图的连通性问题 7.4.1 无向图的连通分量和生成 7.4.2 有向图的强连通分量 7.4.3 最小生成 7.4.4 关节点和重连通分量 7.5 有向无环图及其应用 7.5.1 拓扑排序 7.5.2 关键路径 7.6 最短路径 7.6.1 从某个源点到其余各顶点的最短路径 7.6.2 每一对顶点之间的最短路径 第8章 动态存储管理 8.1 概述 8.2 可利用空间表及分配方法 8.3 边界标识法 8.3.1 可利用空间表的结构 8.3.2 分配算法 8.3.3 回收算法 8.4 伙伴系统 8.4.1 可利用空间表的结构 8.4.2 分配算法 8.4.3 回收算法 8.5 无用单元收集 8.6 存储紧缩 第9章 查找 9.1 静态查找表 9.1.1 顺序表的查找 9.1.2 有序表的查找 9.1.3 静态表的查找 9.1.4 索引顺序表的查找 9.2 动态查找表 9.2.1 二叉排序和平衡二叉树 9.2.2 B和B+ 9.2.3 键 9.3 哈希表 9.3.1 什么是哈希表 9.3.2 哈希函的构造方法 9.3.3 处理冲突的方法 9.3.4 哈希表的查找及其分析 第10章 内部排序 10.1 概述 10.2 插入排序 10.2.1 直接插入排序 10.2.2 其他插入排序 10.2.3 希尔排序 10.3 快速排序 10.4 选择排序 10.4.1 简单选择排序 10.4.2 形选择排序 10.4.3 堆排序 10.5 归并排序 10.6 基排序 10.6.1 多关键字的排序 10.6.2 链式基排序 10.7 各种内部排序方法的比较讨论 第11章 外部排序 11.1 外存信息的存取 11.2 外部排序的方法 11.3 多路平衡归并的实现 11.4 置换一选择排序 11.5 最佳归并 第12章 文件 12.1 有关文件的基本概念 12.2 顺序文件 12.3 索引文件 12.4 ISAM文件和VSAM文件 12.4.1 ISAM文件 12.4.2 VSAM文件 12.5 直接存取文件(散列文件) 12.6 多关键字文件 12.6.1 多重表文件 12.6.2 倒排文件 附录A 名词索引 附录B 函索引 参考书目
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值