第五章 树和二叉树(一)

1.树

  • 定义(递归、嵌套的)
    • n个结点的有限集
      • n=0,空树
      • n>0,满足两个条件
        • 有且仅有一个特定的称为根的结点
        • 其余结点可分为m个互不相交的有限集,其中每一个集合本身又是一颗树,称为根的子树
  • 树的表示方式
    • 常规
    • 嵌套集合
    •  凹入表示
    • 广义表

      •  

2.树的基本术语

  • 结点:数据元素以及指向子树的分支
    • 根结点:非空树中无前驱结点的结点
    • 叶子结点(终端结点):度为0
    • 内部结点(非终端结点):根结点以外的分支结点
    • 结点的度:结点拥有的子树
    • 树的度:树内各结点的度的最大值
  • 深度:树中结点的最大层次
  • 孩子:结点的子树的根称为该结点的孩子
  • 双亲:该结点称为孩子的双亲
  • 兄弟:有共同的双亲
    • 堂兄弟:双亲在同一层的结点
  • 祖先:从根到该结点所经分支上的所有结点
  • 子孙:以某结点为根的子树中的任一结点
  • 有序树:树中结点的各子树从左到右有次序
  • 无序树:树中结点的各子树无次序
  • 森林:m(m>=0)棵互不相交的树的集合
    • 把根结点删除,树就变成了森林
    • 一棵树可以看成一个特殊的森林
    • 给森林中的各子树加上一个双亲结点,森林就变成了树

树结构与线性结构的比较

3.二叉树

  • 定义
    • n个结点的有限集
      • n=0,空集
      • 由一个根结点及两颗互不相交的分别称作根的左子树、右子树的二叉树组成
  • 特点
    • 1每个结点最多有两个孩子
    • 2子树有左右之分,其次序不能颠倒
    • 3二叉树可以是空集合,根可以有空的左子树或空的右子树
  • 注意
    • 二叉树和树是两个概念
  •  二叉树的5种基本形态

  • 两种特殊形式的二叉树(在顺序存储方式下可以复原)

    • 满二叉树

      • 特点

        • 每一层上的结点数都是最大结点树(每层都满)

        • 叶子结点全部都在最底层

      • 满二叉树在同样深度的二叉树中结点个数、叶子结点个数最多

    • 完全二叉树

      •  特点

        • 叶子只可能分布在层次最大的两层上面

        • 对任一结点,如果其右子树的最大层次为i,则其左子树的最大层数必为i或i+1

    • 判断是不是完全二叉树的方法

      • 标号

      • 从满二叉树中,从最后一个结点  连续去掉任意个结点

 4.二叉树的性质和存储结构

性质1:

  在第i层最少有1个结点

性质2:

 深度为k时至少有k个结点

性质3:

 性质4:

 性质5:(完全二叉树中双亲结点编号与孩子结点编号之间的关系)

 二叉树的存储结构

  • 顺序存储:按满二叉树的结点层次编号,依次存放二叉树中的数据元素
    • 缺点:浪费空间
    • 特点:适合满二叉树和完全二叉树
  • 链式存储

例题1

 5.1遍历二叉树

遍历定义:顺着某一条搜索路径巡防二叉树中的结点,使得每个结点均被访问一次,而且仅被访问一次(周游)

遍历方法:

若规定先左后右,则只有三种情况 

 先序遍历二叉树

操作定义:

 中序遍历二叉树

操作定义:

 后序遍历二叉树

操作定义:

例题1

 例题2——用二叉树表示算术表达式

 总结:

1先序:根左右,先遍历根结点,若左子树里面还有子树,继续根据“根左右”进行遍历

2中序:左根右,先遍历最左边的元素,再根据“左根右”继续遍历

3后序:左右根,先遍历最左边的元素,在遍历右子树的元素;若右边是个子树,再继续从“左右根”进行遍历

5.2根据遍历序列确定二叉树

若二叉树中各结点的值均不相同,则二叉树结点的先序序列、中序序列和后序序列都是唯一的

由二叉树的先序序列和中序序列,或由二叉树的后序序列和中序序列可以确定唯一一颗二叉树

例题1——已知先序和中序序列求二叉树

 解:1、由先序知根为A,则由中序知左子树为CDBFE,右子树IHGJ

2、再分别在左、右子树的序列中找出根、左子树序列、右子树序列

 3、以此类推,得到二叉树

 总结:

1先序中的第一个元素往往是根结点,在中序中找到根结点(前面为左子树,后面为右子树)

2先序中第二个元素再在所划分的左子树进行筛选(前面为左子树,后面为右子树)

3(两个元素)在先序中判断出了根结点,在根据中序的定义(左根右)判断后一个元素的位置

例题2——已知中序序列和后序序列求二叉树

 解: 

总结:

1后序(左右根)的最后一个元素为根结点,在中序中划分为左子树和右子树

2划分完的左子树在根据后序中的顺序进行排序,后序中根结点在最后,中序中为左根右

3划分完的右子树以此类推 

5.3遍历(递归)的算法实现

1 先序遍历

先序递归算法研究(先序:ABDC)

 基于c++

 2 中序遍历

 中序遍历递归算法

 3后序算法

后序遍历递归算法

 遍历算法分析

  • 从递归角度看,三种算法是完全相同的(访问路径是相同的),只是访问结点的时机不同
  • 时间效率:O(n),//每个结点只访问一次
  • 空间效率:O(n),//栈占用的最大辅助空间

5.4遍历二叉树的非递归算法

中序遍历非递归算法(思路:栈(后进先出))

 

5.5二叉树的层次遍历算法   

 基本算法:

1 复制二叉树

 2计算二叉树的深度

 3计算二叉树的结点数

 4计算二叉树叶子结点树

5.6 线索二叉树

定义:利用二叉链表中的空指针域 

  • 如果某个结点的左孩子为空,则将空的左孩子指针域改为指向其前驱
  • 如果某个结点的右孩子为空,则将空的右孩子指针域改为指向其后继
  • 线索:改变指向的指针
  • 线索化:对二叉树按某种遍历次序使其变为线索二叉树的过程

标志域

 先序线索二叉树

中序线索二叉树

 

后序线索二叉树 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 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
发出的红包

打赏作者

Memorises1999

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值