数据结构基础:P3.2-树(一)--->二叉树及存储结构

本系列文章为浙江大学陈越、何钦铭数据结构学习笔记,前面的系列文章链接如下
数据结构基础:P1-基本概念
数据结构基础:P2.1-线性结构—>线性表
数据结构基础:P2.2-线性结构—>堆栈
数据结构基础:P2.3-线性结构—>队列
数据结构基础:P2.4-应用实例—>多项式加法运算
数据结构基础:P2.5-应用实例—>多项式乘法与加法运算-C实现
数据结构基础:P3.1-树(一)—>树与树的表示


一、二叉树的定义及性质

1.1 二叉树的定义

二叉树的定义:

二叉树T:一个有穷的结点集合。
----这个集合可以为空。若不为空,则它是由根结点和称为其左子树 T L {{\rm{T}}_{\rm{L}}} TL 和右子树 T R {{\rm{T}}_{\rm{R}}} TR 的两个不相交的二叉树组成。
二叉树具体五种基本形态
在这里插入图片描述
二叉树的子树有左右顺序之分
在这里插入图片描述

特殊二叉树:

①斜二叉树(Skewed Binary Tree):都只有左儿子/右儿子,没有右儿子/左儿子。这样的二叉树实际上就相当于是个链表,形成了一个线性结构。
在这里插入图片描述
②完美二叉树(Perfect Binary Tree):每个结点都有两个儿子(除了最底下这一层的叶结点没有儿子),而且叶结点是比较齐的,都在同一层。所以完美二叉树又叫满二叉树(Full Binary Tree)。
在这里插入图片描述
完全二叉树 (Complete Binary Tree):有n个结点的二叉树,对树中结点按从上至下、从左到右顺序进行编号,编号为i(1≤i≤n)结点与完美二叉树中编号为i结点在二叉树中位置相同。换一种话说,完全二叉树不是满二叉树或者完美二叉树,但是允许缺掉最后这些结点,如下所示:
在这里插入图片描述
但是这种就不是完全二叉树:
在这里插入图片描述


1.2 二叉树的几个重要性质

二叉树有以下性质

① 一个二叉树第 i \rm{i} i 层的最大结点数为: 2 i − 1 , i ≥ 1 {{\rm{2}}^{{\rm{i - 1}}}}{\rm{,i}} \ge {\rm{1}} 2i1,i1
②深度为 k \rm{k} k 的二叉树有最大结点总数为: 2 k − 1 , k ≥ 1 {{\rm{2}}^{\rm{k}}}{\rm{ - 1,k}} \ge {\rm{1}} 2k1,k1。不难理解,将每一层的结点数加起来: 1 + 2 1 + 2 2 + . . . + 2 k − 1 = 2 k − 1 {\rm{1 + }}{{\rm{2}}^{\rm{1}}}{\rm{ + }}{{\rm{2}}^{\rm{2}}}{\rm{ + }}...{\rm{ + }}{{\rm{2}}^{{\rm{k - 1}}}}{\rm{ = }}{{\rm{2}}^{\rm{k}}}{\rm{ - 1}} 1+21+22+...+2k1=2k1
③对任何非空二叉树 T \rm{T} T,若 n 0 {{\rm{n}}_0} n0 表示叶结点的个数、 n 2 {{\rm{n}}_2} n2 是度为2的非叶结点个数,那么两者满足关系 n 0 = n 2 + 1 {{\rm{n}}_0} = {{\rm{n}}_2} + 1 n0=n2+1。我们看个例子:
在这里插入图片描述
其中,叶结点(度为0)的数量 n 0 = 4 {{\rm{n}}_0=4} n0=4 ,度为1的结点数量 n 1 = 2 {{\rm{n}}_1}=2 n1=2,度为2的结点数量 n 2 = 3 {{\rm{n}}_2=3} n2=3。因此,有 n 0 = n 2 + 1 {{\rm{n}}_0} = {{\rm{n}}_2} + 1 n0=n2+1
证明:每个结点我们往上看,都有一条边(除了根结点)。所以从这个角度来看,边的总数等于总的结点数-1。也就是说总的边数 = n 0 + n 1 + n 2 − 1 {\rm{ = }}{{\rm{n}}_0} + {{\rm{n}}_1} + {{\rm{n}}_2} - 1 =n0+n1+n21 。每个结点我们往下看 ,有的有一条边,有的有两条边,有的什么边都没有。也就是说,不同类型的结点对往下边的贡献是不一样的。 n 0 {{\rm{n}}_0} n0的结点就是没有儿子的结点,对往下的边贡献数是 0 × n 0 {\rm{0}} \times {{\rm{n}}_0} 0×n0 n 1 {{\rm{n}}_1} n1 这种结点是有一条往下边的,所以它对于边的贡献总数呢是 1 × n 1 {\rm{1}} \times {{\rm{n}}_1} 1×n1。同样的道理,我们有 n 2 {{\rm{n}}_2} n2 个结点,它往下有2条边。所以从往下看,我们边的总数是这样的: 0 × n 0 + 1 × n 1 + 2 × n 2 {\rm{0}} \times {{\rm{n}}_0} + 1 \times {{\rm{n}}_1} + 2 \times {{\rm{n}}_2} 0×n0+1×n1+2×n2
最终这两个等式相等: n 0 + n 1 + n 2 − 1 {}{{\rm{n}}_0} + {{\rm{n}}_1} + {{\rm{n}}_2-1} n0+n1+n21 = 0 × n 0 + 1 × n 1 + 2 × n 2 {\rm{0}} \times {{\rm{n}}_0} + 1 \times {{\rm{n}}_1} + 2 \times {{\rm{n}}_2} 0×n0+1×n1+2×n2

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

类型名称:二叉树
数据对象集:一个有穷的结点集合。若不为空,则由根结点和其左、右二叉子树组成。
操作集 B T ∈ B i n T r e e , I t e m ∈ E l e m e n t T y p e {\rm{BT}} \in {\rm{BinTree,Item}} \in {\rm{ElementType}} BTBinTree,ItemElementType,重要操作有:
----1、Boolean IsEmpty( BinTree BT ): 判别BT是否为空;
----2、void Traversal( BinTree BT ):遍历,按某顺序访问每个结点;
----3、BinTree CreatBinTree( ):创建一个二叉树。
常用的遍历方法有
void PreOrderTraversal( BinTree BT ):先序----根、左子树、右子树;
void InOrderTraversal( BinTree BT ): 中序----左子树、根、右子树;
void PostOrderTraversal( BinTree BT ):后序----左子树、右子树、根
void LevelOrderTraversal( BinTree BT ):层次遍历,从上到下、从左到右


二、二叉树的存储结构

下面我们来讲一下二叉树的存储结构,也就是说二叉树怎么进行表示。首先一个自然想到的,有没有可能用数组来表示二叉树。前面我们提到过,一般的树用数组来实现是很困难的。但二叉树因为它的分支比较少,最多只有两个儿子,有没有可能用数组实现呢?

使用数组表示完全二叉树

有一种树用数组实现非常方便,就是我们前面提到过的完全二叉树。因为完全二叉树我们看到除了最底下这一层,前面的结点的全部放在满了。我们可以从上往下、从左往右对它进行编号,这个编号是连续的。
在这里插入图片描述
然后我们把这个编号跟一个数组的下标对应起来,把根结点放在数组下标为1的地方,它的左右儿子放在下标为2 3 的地方,如此循环下去。
在这里插入图片描述
可以看出,我们可以把完全二叉树放在一个数组里面。关键是 放好了之后我想找出他们之间的关系容易不容易。
①非根结点(序号 i > 1 {\rm{i > 1}} i>1)的父结点的序号是 ⌊ i / 2 ⌋ \left\lfloor {{\rm{i/2}}} \right\rfloor i/2;
②结点(序号为 i \rm{i} i) 的左孩子结点的序号是 2 i \rm{2i} 2i,(若 2 i ≤ n {\rm{2i}} \le {\rm{n}} 2in,否则没有左孩子);
③结点(序号为 i \rm{i} i) 的右孩子结点的序号是 2 i + 1 \rm{2i+1} 2i+1,(若 2 i + 1 ≤ n {\rm{2i + 1}} \le {\rm{n}} 2i+1n,否则没有右孩子);

使用数组表示一般二叉树

一般的二叉树意味着可能有这边缺一些结点,那边缺一个结点。我们也可以用类似这种方法存储一般二叉树,我会把一般的二叉树补充成一个完全二叉树,相应缺的结点 在数组里面留下一个空位。
在这里插入图片描述
所以对一般的这样的一个二叉树,如果我们用数组这样的方法来进行存储时具体情况如下所示。
在这里插入图片描述
在这个数组中,前面提到的对应关系仍然存在。比方说M,它的父亲是6的1/2=3。O的左儿子是2i=3x2=6,就是M。当然这种存储是有缺点的,有很多空间对应的结点是空的,但是我们必须给它留着位置。作为例子的二叉树我们只有5个结点,但是我们需要用13个位置来存这5个结点,会造成一定的空间浪费

链表存储

在一般树的时候我们就是用链表,左儿子 - 右兄弟这种方法来存储。对于正规的二叉树我们同样也可以用这种方法,每个结点可以用这样的结构来表示:3个域,一个代表信息、一个指向左儿子、一个指向右儿子。
在这里插入图片描述
所以对于这样的一个例子,我们很容易就对应地用这样的包含两个指针的结构来实现一个链式存储的二叉树。对应来讲,没儿子的地方我们可以用NULL表示。具体如下面这个例子所示:
在这里插入图片描述

链表存储对应数据结构的代码如下

typedef struct TreeNode *BinTree;
typedef BinTree Position;
struct TreeNode{
	ElementType Data;
	BinTree Left;
	BinTree Right;
}

三、小测验

1、如果一个完全二叉树最底下一层为第六层(根为第一层)且该层共有8个叶结点,那么该完全二叉树共有多少个结点?

A. 31
B. 39
C. 63
D. 71

答案:B

2、若有一二叉树的总结点数为98,只有一个儿子的结点数为48,则该树的叶结点数是多少?

A. 25
B. 50
C. 不确定
D. 这样的树不存在

答案:D

3、设深度为d(只有一个根结点时,d为1)的二叉树只有度为0和2的结点,则此类二叉树的结点数至少为2d-1
答案:正确

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

知初与修一

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

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

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

打赏作者

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

抵扣说明:

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

余额充值