一、二叉树的定义
【1】定义
二叉树是一种树形结构,每个结点最多只有两棵子树(即二叉树中不存在度大于2的结点),子树有左右之分(是有序树)。
【2】例子
【3】二叉树的基本形态
①空二叉树 | ②只有根结点 | ③只有左子树 | ④只有右子树 | ⑤左右子树都有 |
【4】区分二叉树和度为2的树
①度为2的树至少有3个结点;二叉树可以为空。
②二叉树无论其孩子数是否为2均需确定其左右次序;度为2的有序树,如果某个结点只有一个孩子结点,这个孩子结点就无须区分其左右次序。
二、二叉树的性质
【1】非空二叉树上叶子结点数(度为0) = 度为2的结点数+1
原理:
【2】非空二叉树上第K层至多有个结点(K>=1)
【3】高为H的二叉树上至多有个结点
【4】给定n个结点能构成种不同形态的二叉树(Catalan函数)
原理:
Catalan函数有多种形式,数据结构不需要学习。我们只需要知道h(n) = h(n-1)*h(0) + h(n-2)*h(1) + ··· + h(0)*h(n-1) =(n>=2)为Catalan函数的其中一种形式即可。
三、几个特殊的二叉树
1、斜树
【1】定义
左斜树 | 除叶子结点外的所有结点都只有左子树的二叉树叫左斜树 |
右斜树 | 除叶子结点外的所有结点都只有右子树的二叉树叫右斜树 |
【2】例子
【3】特点
线性结构可以理解为是树的一种极其特殊的表现形式。
2、满二叉树
【1】定义
①一棵高度为h,并且含有个结点的二叉树称为满二叉树。
②所有分支结点都存在左子树和右子树,所有叶子都在同一层上,这样的二叉树称为满二叉树。
【2】例子
【3】说明
①满二叉树的每一层都含有最多的结点。
②满二叉树的叶子结点都集中在二叉树的最下一层。
③除叶子结点之外的每个结点度数均为2。
④在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。
【4】对满二叉树按层序编号
①编号规则:约定编号从根结点(根结点编号为1)起;自上而下,自左向右(层序)。
②规律:对于编号为i的结点,如果有双亲,其双亲为floor(i/2);如果有左孩子,则左孩子为2i;如果有右孩子,则右孩子为2*i+1。
3、完全二叉树
【1】定义
对满二叉树按编号递减(从右至左、从下至上)进行结点删除,得到的树都是完全二叉树。
【2】例子
如果不挨个删,则得到的不是完全二叉树,满二叉树是一种特殊的完全二叉树。文字定义虽繁琐,但是直接看图,一切描述都在你我眼中。
【3】特点
①叶子结点只能出现在最下两层。
②最下层的叶子一定集中在左部连续位置。
③倒数二层,若有叶子结点,一定都在右部连续位置。
④如果结点度为1,则该结点只有左孩子,即不存在只有右子树的情况。
⑤度为1的结点只能是1或者0个。
⑥同样结点数的二叉树,完全二叉树的深度最小。
【4】完全二叉树(设高为h,有n个结点)的性质
①如果i <= floor(n/2),则结点i为分支结点【floor(n/2)是最后一个度不为0的结点】;否则i为叶子结点。
②叶子结点可能出现的位置为最后一层(集中在左边)和倒数第二层(集中在右边)。
③度为1的结点要么只有1个(有左孩子,无右孩子),要么没有。
④结点i(度为1或0),则编号大于i的结点均为叶子结点。
⑤n为奇数时,每个分支结点都有左右子女【满二叉树时,最后一个结点编号是奇数,此时所有分支结点都是双分支】;n为偶数时,编号最大的分支结点floor(n/2)只有左孩子。
⑥结点i(i>1)的双亲结点编号为floor(i/2)。
i为偶数 | 双亲结点编号为i/2,i是双亲的左孩子 |
i为奇数 | 双亲结点编号为(i-1)/2,i是双亲的右孩子 |
⑦结点i的左孩子编号。
2*i<=n(有左孩子) | 结点i的左孩子编号为2i |
2*i>n(无左孩子) | 结点i的左孩子不存在 |
⑧结点i的右孩子编号。
2*i+1<=n(有右孩子) | 结点i的右孩子编号为2i+1 |
2*i+1>n(无右孩子) | 结点i的右孩子不存在 |
⑨结点i的深度(层次)。
⑩完全二叉树的高度(深度)为,该值也是有n个结点的二叉树的深度的最小值,在数学推导中,和是相等的。
4、二叉排序树
【1】定义
①是二叉树。
②左子树上所有关键字均小于根,右子树上所有关键字均大于根,左右子树都是二叉排序树。
【2】例子
5、平衡二叉树
【1】定义
①是二叉排序树。
②树中任意结点左右子树的深度之差不超过1。
【2】例子
四、二叉树的存储结构
1、顺序存储结构
【1】思想
①用一组地址连续的存储单元依次自上而下、自左至右存储完全二叉树上的结点元素。
②按序号依次存储。
③父子关系由前面说述的完全二叉树的性质计算得到(为了完全对应上,数组也从下标1开始存储)。
【2】注解
①完全二叉树和满二叉树采用顺序存储比较合适。
②一般的二叉树采用该方法存储,只能添加一些并不存在的空结点让其每个结点与完全二叉树上的结点相对照。
③本篇文章二叉树的顺序存储结构与上篇文章树的顺序存储结构(双亲表示法)不同。
2、链式存储结构
【1】背景
顺序存储结构存储普通的二叉树时,对空间的利用率比较低。
这里的链式存储结构其实就是上篇文章所介绍的树的孩子兄弟表示法(二叉链表),该方式将是重点研究的。
【2】思想
①用二叉链表来存储一棵二叉树。
②二叉树中每个结点用一个链表的结点来表示。
③二叉链表结点域包含数据域、左指针域、右指针域。
【3】存储结构描述
typedef struct BiTNode
{
ElemType data; // 数据域
struct BiTNode* lchild, // 左孩子指针域
* rchild; // 右孩子指针域
}BiTNode, * BiTree;
【4】例子
【5】注解
n个结点的二叉链表中,含有n+1个空指针域(n个结点,总共有2n个指针域;n个结点,存在n-1条边,共占用n-1个指针域;还剩下2n-(n-1) = n+1个空指针域)。