数据结构_study(五)

n(n>=0)个结点的有限集
空树:n=0

在非空树中:
有且仅有一个特定的根root结点;
n>1时,其余结点可以分为m个互不相交的有限集,其中每个集合也是一棵树,根的子树

一对多

结点的度:结点拥有的子树数
树的度:树内各结点的度的最大值
叶(终端)结点:度为0
分支(非终端)结点:度不为0
内部节点:除根结点之外的分支结点
在这里插入图片描述
结点—结点的子树的根
双亲孩子

统一个双亲的孩子互称兄弟
祖先:根到该结点所经分支上的所有结点
子孙:以结点为根的子树的任意结点

根:无双亲,叶结点:无孩子
中间结点:一个双亲多个孩子
在这里插入图片描述
层次:从根开始定义,根是第1层,根的孩子是第2层依次类推
双亲在同一层的结点互为堂兄弟
树的深度\高度:结点的最大层次
在这里插入图片描述
有序树:各子树从左至右是有次序的,不可互换

森林:m(m>=0)棵互不相交的树的集合
对树中的每个结点而言,子树的集合即为森林

抽象数据类型

树(tree)
Data
树是由一个根结点和若干棵子树构成。树中结点具有相同数据类型及层次关系
Operation

InitTree(*);构造空树T。
DestroyTree(*T) : 销毁树T。
CreateTree(*Tdefinition) : 按definition中给出树的定义来构造树。
ClearTree(*T) : 若树存在,则将树I清为空树。
TreeEmpty(T) : 若为空树,返回true,否则返回false。
TreeDepth(T) : 返回T的深度。
Root(T) : 返回T的根结点。
Value(T, cur e) : cur e是树T中一个结点,返回此结点的值。
Assign(T, cure, value) : 给树的结点cure值为value。
Parent(T, cure) : 若cure是树的非根结点,则返回它的双亲,否则返回空。
LeftChild(T, cure) : 若cur e是树里的非叶结点,则返回它的最左孩子,否则返回空。
RightSibling(T, cure) : 若cure有右兄弟,则返回它的右兄弟,否则返回空。
InsertChild(*T, *p, i, c) : 其中p指向树里的某个结点,i为所指结点p的度加上1, 非空树c与T不相交,操作结果为插入c为树T中p指结点的第i棵子树。
DeleteChild(*T, *p, i) : 其中p指向树里的某个结点,i为所指结点p的度,操作 结果为删除T中p所指结点的第i棵子树。

双亲表示法

在每个结点中,指示双亲结点的位置

数据域:存储结点的数据信息
指针域:存储结点的双亲在数组的下标

找双亲结点时间复杂度O(1)
找孩子结点,需要遍历整个结构

关注结点的孩子,增加长子域:结点最左边孩子的域
关注结点的兄弟,增加右兄弟域:右兄弟下标
在这里插入图片描述

孩子表示法

多重链表表示法
每个结点有多个指针域,每个指针指向一棵子树的根结点

树的每个结点的度,孩子个数不同
1、指针域的个数以树的度(结点度的最大值)为准
当结点度相差很大时,浪费空间
在这里插入图片描述

2、每个结点指针域的个数等于结点的度,取一个位置存指针域个数
不会有空间浪费
结点链表不同结构,需要维护结点的度的值,时间损耗
在这里插入图片描述

孩子表示法
n个结点
每个结点的孩子,排列做单链表,n个孩子链表
叶子结点链表为空
n个头指针,做线性表,一维数组

便于遍历整棵树,找某个结点的孩子,兄弟,不方便找双亲
在这里插入图片描述
双亲孩子表示法
在孩子表示法的基础上加双亲,方便找双亲
在这里插入图片描述

孩子兄弟表示法

结点的第一个孩子,存在就是唯一
第一个孩子的右兄弟,存在就是唯一
两个指针指向第一个孩子和其右兄弟

方便查找某个结点的某个孩子
在这里插入图片描述

二叉树

n(n>=0)个结点的有限集合
n=0,空二叉树
n>1,一个根节点、根节点的(两颗互不相交的)左右子树

每个结点最多有2棵子树,0,1,2
左右子树有顺序,不可随意颠倒
一棵子树时也要区分左右

5种基本形态:

  1. 空二叉树
  2. 只有一个根节点
  3. 根节点+左子树
  4. 根节点+右子树
  5. 根节点+左子树+右子树

3个结点的树的5种情况
在这里插入图片描述
特殊二叉树:

  • 斜二叉树:每层只有一个结点,结点个数=二叉树的深度
    左斜树:所有结点都只有左子树
    右斜树:所有结点都只有右子树
  • 满二叉树:每个结点都有左右子树(每个结点的度都为2),所有叶子结点都在同一层(最下层)
    同样深度的二叉树,满二叉树的结点个数最多,叶子最多
  • 完全二叉树:按层序排号,编号和满二叉树相同的结点位置也相同
    叶子结点只能在最下两层,
    结点度为1时,只有左孩子
    最下层的叶子在左边连续,倒数第二层的叶子在右边连续
    同样结点树的二叉树,完全二叉树深度最小

性质

  1. 第 i 层上至多有2i-1个结点(i>=1)
  2. 深度为 k 的二叉树至多有2k-1个结点
  3. 叶子结点个数n0,度为2的结点个数n2,n0=n2+1;
  4. 具有n个结点的完全二叉树深度为(小于log2n的最大整数)+1,具有n个结点的满二叉树深度为log2(n+1)
  5. n个结点的完全二叉树,层序编号,对任一结点i
    i=1,结点为根,i>1,双亲是结点(小于i/2的最大整数)
    2i>n,i 为叶子,无左孩子;否则左孩子是2i
    2i+1>n,i 无右孩子;否则右孩子是2i+1

顺序存储

一维数组存储结点,数组下标体现结点之间的逻辑关系

按完全二叉树的层序编号,不存在的结点设为空

最适合完全二叉树,其他情况浪费空间

二叉链表

二叉链表:一个数据域,两个指针域
在这里插入图片描述

遍历二叉树

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

前序

根左右

二叉树为空,返回
根开始,前序左子树,前序右子树
在这里插入图片描述

中序

左根右

二叉树为空,返回
中序左子树,访问根节点,中序右子树
在这里插入图片描述

后序

左右根

二叉树为空,返回
后序序左子树,后序右子树,访问根节点
在这里插入图片描述

层序

根开始,从上而下,从左到右
在这里插入图片描述

已知前序+中序,可以确定一棵二叉树
已知后序+中序,可以确定一棵二叉树

建立二叉树

扩展二叉树:二叉树的每个结点的空指针引出一个虚结点,特定值,比如‘#’

通过扩展二叉树的一个遍历序列确定树

键盘输入扩展二叉树的前序序列AB#D##C##,一次性输入,递归生成树

也可以用创建结点的函数,反复调用
在这里插入图片描述

线索二叉树

n个结点,2n个指针域,n+1个空指针域,浪费空间
结点的前驱和后继每次都需要遍历

线索:指向前驱和后继的指针
线索链表:加上线索的二叉链表
线索二叉树:加上线索的二叉树
线索化:二叉树以某种次序遍历变为线索二叉树的过程,即把二叉链表中的空指针改为前驱和后继

增加标志ltag、rtag确定是指向左孩子\右孩子还是前驱\后继
tag是0,1布尔型变量,比指针变量占用内存小
在这里插入图片描述
在二叉树线索链表上添加一个头结点
在这里插入图片描述
充分利用空指针,减少空间浪费
创建时的一次遍历就可以一直使用前驱后继的信息,减少时间

需要经常遍历,或需要前驱和后继,适合使用线索二叉树

哈夫曼树

文件压缩
哈夫曼编码:基本压缩编码方法

哈夫曼树:带权路径长度最小的二叉树

两个结点之间的路径:树中一个结点但到另一个结点之间的分支
路径长度:路径上的分支数目
树的路径长度:从树根到每一结点的路径长度之和

结点的带权路径长度:该结点到树根之间的路径长度与结点上权的乘积
树的带权路径长度:结点带权路径长度之和
在这里插入图片描述
生成哈夫曼树
1、有权值的叶子从小到大排序,A5,E10,B15,D30,C40
2、最小权值的2个结点AE作为新结点N1的两个子结点,最小的做左孩子,N1权值为5+10=15
3、N1代替AE插入到序列N115,B15,D30,C40
4、重复步骤2
5、全部插入,完成
在这里插入图片描述
算法描述
在这里插入图片描述

哈夫曼编码

远距离传输电报的数据传输的最优问题

需要编码的字符集:{d1,d2,d3,…dn},作为叶子结点
字符在电文中出现的次数或频率集合:{w1,w2,w3,…wn},作为相应叶子节点的权值
构造的哈夫曼树
左分支:0,右分支:1
从根节点到叶子结点经过的路径分支组成的0,1的序列,则为对应字符的编码

编码和解码需要约定好相同的哈夫曼编码规则
在这里插入图片描述

树,森林,二叉树

树:一个结点有任意多个孩子
二叉树:只有左右孩子
森林:若干棵树

树转换为二叉树
1、所有兄弟结点之间加一条线
2、每个结点,只保留和第一个孩子之间的连线,去掉和其他孩子的连线
3、层次调整,结点:第一个孩子是左孩子,兄弟是右孩子
在这里插入图片描述

森林转换为二叉树:
1、每棵树都转换为二叉树
2、第一棵树不动,后一棵二叉树的根节点做前一棵树的根节点的右孩子
在这里插入图片描述
二叉树转换为树
1、结点的左孩子的n个右孩子结点,都作为此结点的孩子
2、删除二叉树中所有结点和右孩子的连线
3、层次调整在这里插入图片描述
二叉树转换为森林
二叉树的根节点有右孩子就是森林,没有就是一棵树
1、根节点开始,和右孩子的连线删除
2、分离的二叉树转换为树
在这里插入图片描述
树的遍历
1、先根遍历,先访问根,再依次先根遍历子树
2、后根遍历,先依次后根遍历子树,再访问根
森林遍历
1、前序,先第一棵树的根,再依次遍历根的每棵子树,再同样方式遍历剩余树(和二叉树的前序遍历结果相同)
2、后序,先第一棵树,后根遍历每棵子树,再访问根结点,再同样方式遍历剩余树(和二叉树的中序遍历结果相同)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值