数据结构与算法(六)

树的存储结构

实现树结构的存储方式

双亲表示法

以双亲作为索引的关键词的一种存储方式

  • 以一组连续空间存储树的结点,同时在每个结点中,附设一个指示其双亲结点在数组中位置的元素

所以可以根据某结点的parent指针找到它的双亲结点,所用时间复杂度为O(1),索引到parent=-1,表示找到树结点的根。

如果要知道某结点的孩子,则要遍历整个树。

孩子表示法

多重链表

  • 方案一:根据树的度,声明足够空间存放子树指针的结点
    浪费空间
  • 方案二:数据后面有一个值来表示指针的个数
    每个结点的度的值不同,初始化和维护起来难度巨大
  • 方案三:根数据后面连接着子结点位置的指针

双亲孩子表示法

孩子后面存储跟结点的指针,同时又有指向子结点的指针

二叉树

定义:二叉树(Binary tree)是n(n>=0)个结点的有限集合,该集合或者为空集(空二叉树),或者由一个根结点和两颗互不相交的,分别为根结点的左子树和右子树的二叉树组成。

性质:

  • 每个结点最多有两个子树,所以二叉树中不存在度大于2的结点。
  • 左子树和右子树是有顺序的,次序不能颠倒
  • 即使树中某结点只有一颗子树,也要区分它是左子树还是右子树

二叉树的五种基本形态

  • 空二叉树
  • 只有一个根结点
  • 根结点只有左子树
  • 根结点只有右子树
  • 根结点既有左子树尤游右子树

特殊二叉树

斜树(左斜、右斜)

满二叉树

满二叉树所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。

  • 叶子只能出现在最后一层
  • 非叶子的结点的度都是2
  • 在同样深度的树中,二叉树的结点是最多的

完全二叉树:

对一颗具有n个结点的二叉树按层序编号,如果编号为i(1<=i<=n)的结点与同样深度的满二叉树中编号为i 的结点位置完全相同,则这颗二叉树称为完全二叉树。

完全二叉树的特点
  • 叶子结点只能出现在最下两层
  • 最下层的叶子一定集中在左部连续位置
  • 倒数第二层,若有叶子结点,一定都在右部连续位置
  • 如果结点度为1,则该结点只有左孩子
  • 同样结点树的二叉树,完全二叉树的深度最小
  • 满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树

二叉树的性质:

  • 一:二叉树的第i层上至多有2^(i-1)个结点
  • 二:深度为k的二叉树至多有2^k-1个结点(k>=1)
  • 三:对任何一颗二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1
  • 四:具有n个结点的完全二叉树的深度为[log2 n]+1
  • 五:如果对一颗有n个结点的完全二叉树的结点按层序编号,对于任一结点i(1<=i<=n)有以下性质:
    如果i=1,则结点时二叉树的根,无双亲;若果i>1,则其双亲是结点[1/2]
    如果2i>n,则结点i无左孩子(结点i为叶子结点);否则其左孩子是结点2i
    如果2i+1>n,则结点i无右孩子;否则其右孩子是结点2i+1

二叉树的存储结构:

二叉树的顺序存储结构就是用一维数组存储二叉树中的各个结点,并且结点的存储位置能体现结点之间的逻辑关系
对于一般的二叉树,尽管层序编号不能反映逻辑关系,但是也可以按照完全二叉树编号方式修改一下,把不存在的结点用“^”代替
顺序存储方式的适用性不强,二叉树也可以采取链式存储结构

二叉树每个结点最多有两个孩子,所以为它设计一个数据域和两个指针域是比较自然的想法,我们称这样的链表叫做二叉链表

lchilddatarchild

二叉树的遍历

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

前序遍历

若二叉树为空,则空操作返回,否则先访问根及诶单,然后前序遍历左子树,再前序遍历右子树

中序遍历

若树为空,则空操作返回,否则从根结点开始(注意不是先访问根结点,先从左子树开始),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树

后序遍历

若树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后访问根结点。

层序遍历

线索二叉树

lchildltagdatartagrchild

ltag为0时指向该结点的左孩子,为1时指向该结点的前驱
rtag为0时指向该结点的右孩子,为1时指向该结点的后继

树、森林及二叉树的相互转换

树到二叉树的转换:
  • 第一步:在树中所有兄弟结点之间加一连线
  • 第二步:对每个结点,除了保留与其的长子的连线外,去掉该结点与其他孩子的连线
    注:兄弟都变成右儿子
森林转化为二叉树
  • 第一步:先将森林中的每棵树先变成二叉树
  • 第二步:将各二叉树的根结点视为兄弟从左至右连在一起,就形成了一棵二叉树
  • 第三步:调整位置
二叉树到树、森林的转换
  • 第一步:若结点x是双亲y的左孩子,则把x的右孩子、右孩子的右孩子、……、都与y用连线连起来
  • 第二步:去除所有双亲到右孩子之间的连线
判断一棵二叉树能够转换成一棵树还是森林

看这棵二叉树的根结点有没有右孩子,有的话就是森林,没有的话就是一棵树

树的遍历

先根遍历:先访问树的根结点,然后再依次先根遍历每棵子树

后根遍历:先依次遍历每棵子树,然后再访问根结点

森林的遍历

前序遍历和后序遍历,其实就是按照树的先根遍历和后根遍历依次访问森林的每一棵树

注:树、森林的前根(序)遍历和二叉树的前序遍历结果相同,树、森林的后根(序)遍历和二叉树的中序遍历结果相同。

赫夫曼树(哈夫曼树)

定义与原理:把二叉树简化成叶子结点带权的二叉树(注:树结点间的连线相关的数叫做权)

  • 结点的路径长度:
    从根结点到该结点的路径上的连接数
  • 树的路径长度:
    树中每个叶子结点的路径长度之和
  • 结点带权路径长度:
    结点的路径长度与结点权值的乘积
  • 树的带权路径长度:
    WPL(weighted path length)是树中所有叶子及诶单的带权路径长度之和

WPL的值越小,说明构造出来的二叉树性能越优

构造哈夫曼树(最优二叉树)

权值越小的在远离根的一段

注:赫夫曼编码——无损编码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值