数据结构-树

引例

基本概念定义和特性

树的特性:

1.第一个属性是层次性,即树是按层级构建的,越笼统就越靠近顶部,越具体则越靠近底部.

2.的第二个属性是相互独立性,一个节点的所有子节点都与另一个节点的所有子节点无关。

3.第三个属性是,叶子节点都是独一无二的

基本术语

节点:树的基础部分,称作“”。在字典中,或者说在散列表当中也是用key表示某个单位的。带有附加信息,我们称作“有效载荷”。这个和图是一样的,树就是一种图。

边:边是树的另一个基础部分。两个节点通过一条边相连,表示它们之间存在关系。除了根节点以外,其他每个节点都仅有一条入边,出边则可能有多条。

根节点:根节点是树中唯一没有入边的节点
父节点:一个节点是其所有子节点的父节点
子节点:一个节点通过出边与子节点相连
兄弟节点:具有同一父节点的节点互称为兄弟节点
叶子节点:叶子节点没有子节点

度:一个节点拥有的子树数
路径:路径是由边连接有序节点列表。
有序树:结点各子树从左至右有序,不能互换(左为第一)
无序树:结点各子树可互换位置。
森林:指m棵不相交的树的集合

树的其他表达方式

嵌套集合

广义表

凹入表示

树的具体探究

树(Tree)是n(n≥0)个节点的有限集,它或为空树(n=0);或为非空树,树可以为空树。

对于非空树T:

1.有且仅有一个称之为根的节点;
2.除根节点以外的其余节点可分为m(m>0)个互不相交的有限集T1, T2, …, Tm, 其中每一个集合本身又是一棵树,并且称为根的子树(SubTree)。
3.从根节点到其他每个节点都有且仅有一条路径

二叉树的定义

1.二叉树是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式
2.二叉树是指树中节点的度不大于2的有序树(左右不能够交换)

普通树(多叉树)若不转化为二叉树,则运算很难实现,二叉树结构最简单,规律性最强


具有3个结点的二叉树可能有几种不同形态?普通树呢?

因为二叉树是有序树,所以有五种,普通无序树只有两种



二叉树具有五种基本形式:


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

二叉树的性质

性质1: 在二叉树的第i层上至多有2^{i-1}个结点,至少有一个

性质2: 深度为k的二叉树至多有2^{k}-1个结点,至少有k个

性质3: 对于任何一棵二叉树,若2度的结点数有n2个,则叶子数n0必定为n2+1 (即n0=n2+1)

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

具有n 个节点的满二叉树的深度为𝑙𝑜𝑔2(𝑛+1)

特殊形态二叉树 

满二叉树:一棵深度为k 且有2^{k} -1个结点的二叉树。

完全二叉树:深度为k 的,有n个结点的二叉树,当且仅当其每一个结点都与深度为k 的满二叉树中编号从1至n的结点一一对应

 满二叉树是完全二叉树的一个特例。

树在计算机中的存储结构

数组存储

二叉树并不适合用数组存储,因为并不是每个二叉树都是完全二叉树,普通二叉树使用顺序表存储或多或多会存在空间浪费的现象。

 顺序存储特点:
•节点间关系蕴含在其存储位置中
•浪费空间,适于存满二叉树完全二叉树

链表链式存储

一棵普通的二叉树,若将其采用链式存储,

则只需从树的根节点开始,将各个节点及其左右子节点使用链表存储即可

链式存储

 因此,采用链式存储二叉树时,其节点结构由3 部分构成
1.指向左子节点的指针
2.节点存储的数据
3.指向右子节点的指针

二叉树的遍历方式

遍历定义

指按某条搜索路线遍访每个结点且不重复(又称周游)。

遍历用途

它是树结构插入、删除、修改、查找排序运算的前提,是二叉树一切运算的基础和核心。

线性数据结构中,对其所有数据项的访问比较简单直接,按照顺序依次进行即可
二叉树是一种非线性结构,而我们对其执行遍历操作时所得的序列是线性的,因此我们需要找到一种遍历方式,在对具有非线性结构的二叉树执行遍历操作后,得到一个线性序列。

二叉树的遍历方式

我们已经了解了树的基本功能,现在是时候看看都有哪些遍历方式了,二叉树共有4种基本的遍历方式:
1.前序遍历
2.中序遍历
3.后序遍历
4.层序遍历

1.若二叉树为空,则空操作
否则访问根结点(D)

前序遍历左子树(L)

前序遍历右子树(R)

前序遍历序列:A B D C

1.前序遍历
在前序遍历中,先访问根节点,然后递归地前序遍历左子树,最后递归地前序遍历右子树。
以读一本书为例,前序遍历即按照书的章节顺序阅读:第一章→1.1→1.2→1.2.1→1.2.2

2. 中序遍历
在中序遍历中,先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。
这种方式实际上是首先从下到上遍历一个节点的左子树,在到达该节点之后又开始从下到上遍历另一棵树,如图遍历的顺序为HDIBEJAFKCG。

 

 3.后序遍历

若二叉树为空,则空操作
否则后序遍历左子树(L)后序遍历右子树(R)访问根结点(D)

在后序遍历中,先递归地后序遍历左子树,然后递归地后序遍历右子树,最后访问根节点。
如图遍历的顺序为HIDJEBKFGCA。

遍历规则

先序遍历:A B D E C
中序遍历:D B E A C
后序遍历:D E B C A
 

 口诀:
DLR—先序遍历,即先根再左再右
LDR—中序遍历,即先左再根再右
LRD—后序遍历,即先左再右再根

4.层序遍历
在层序遍历中,若树为空,则空操作返回,否则从树的第一层,也就是根结点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。
如图遍历的顺序为ABCDEFGHIJK。

 用二叉树表示算术表达式

 遍历算法分析
如果去掉输出语句,从递归的角度看,三种算法是完全相同的,或说这三种算法的访问路径是相同的,只是访问结点的时机不同。

 从虚线的出发点到终点的路径上,每个结点经过3次。

第1次经过时访问=先序遍历
第2次经过时访问=中序遍历
第3次经过时访问=后序遍历

时间效率:O(n)
//每个结点只访问一次 

空间效率:O(n)
//栈占用的最大辅助空间

哈夫曼树

哈夫曼树


先通过一个小例子来引出哈夫曼树,例:将学生的百分制成绩转换为五分制成绩:≥90 分: A,80~89分: B,70~79分: C,60~69分: D,<60分: E。
编制一个程序,将百分制转换成五个等级输出

if grade >= 90:
    print('A')
elif grade >= 80 and grade < 90:
    print('B')
elif grade >= 70 and grade < 80:
    print('C')
elif grade >= 60 and grade < 70:
    print('D')
else:
    print('E')

若考虑上述程序所耗费的时间,就会发现该程序的缺陷。

在实际中,学生成绩在五个等级上的分布是不均匀的

当学生百分制成绩的录入量很大时,上述判定过程需要反复调用,此时程序的执行效率将成为一个严重问题

上述判断方式对应的判别树如下:
如果学生的总成绩数据有10000条,则5%的数据需1 次比较,15%的数据需2 次比较,40%的数据需3 次比较,40%的数据需4 次比较
因此10000 个数据比较的次数为:10000 (5%+2×15%+3×40%+4×40%)=31500次

再看另一种判断方式:
此种形状的二叉树,需要的比较次数是:10000 (3×20%+2×80%)=22000次
显然:两种判别树的效率是不一样的

 给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小

称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。

 

      普通二叉树                                                               哈夫曼树  

 哈夫曼树相关的概念:


1.路径:从树中一个结点到另一个结点之间的分支序列构成两个节点间的路径
2.结点的权:给树中结点赋予一个数值,该数值称为结点的权
3.带权路径长度:结点到树根间的路径长度与结点的权的乘积,称为该结点的带权路径长度
4.树的带权路径长度:树中所有叶子结点的带权路径长度之和,通常记为WPL

带权路径长度:假设结点H的权重是3,从根结点到结点H的路径长度也是3,因此结点H的带权路径长度是3 ×3 = 9

树的带权路径长度:仍然以这颗二叉树为例,树的路径长度是3 ×3 + 6 ×3 + 1 ×2 + 4 ×2 + 8 ×2 = 53

 举个例子,给定权重分别为1,3,4,6,8的叶子结点,我们应当构建怎样的二叉树,才能保证其带权路径长度最小
原则上,我们应该让权重小的叶子结点远离树根,权重大的叶子结点靠近树根

哈夫曼树的构建


下面具体讲解如何构建哈夫曼树?
假设有6个叶子结点,权重依次是2,3,7,9,18,25

 

基本思想:使权大的结点靠近根
操作要点:对权值的合并、删除与替换,总是合并当前值最小的两个

我们把每一个叶子结点,都当做树一颗独立的树(只有根结点的树),这样就形成了一个森林
在上图当中,右侧是叶子结点的森林,左侧是一个辅助队列,按照权值从小到大存储了所有叶子结点。至于辅助队列的作用,我们后续将会看到。

从队列中移除上一步选择的两个最小结点,把新的父节点加入队列,也就是从队列中删除2和3,插入5,并且仍然保持队列的升序:

哈夫曼树的构建
选择当前权值最小的两个结点,生成新的父结点

 

 重复该过程

 

 50
哈夫曼树的构建
为了使得到的哈夫曼树的结构尽量唯一,通常规定生成的哈夫曼树中每个结点的左子树根结点的权小于等于右子树根结点的权

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就是随便学学

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

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

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

打赏作者

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

抵扣说明:

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

余额充值