特点:非线性结构,一个直接前驱,但可能有多个直接后继(1:n)
树的基本概念
1. 树的定义
树是n个(n≥0)结点的有限集。在任意一颗非空树中
(1)有且仅有一个结点称为根(root)
(2)当n>1时,其余的结点分为m(m>0)个互不相交的有限集合T1,T2,…,Tm。
每个集合本身又是一棵树,被称作这个根的子树 。
树的抽象数据类型定义
树的表示法
嵌套集合表示法
目录表示法
图形表示法
广义表表示法
左孩子-右兄弟表示法
图形表示法
广义表表示法
( A ( B ( E ( K, L ), F ), C ( G ), D ( H ( M ), I, J ) ) 根作为由子树森林组成的表的名字写在表的左边
左孩子-右兄弟表示法
一颗普通的有序树可以用唯一的一个二叉树表示,这个二叉树也可以转换成它对应的那颗普通树。
2 若干术语
根:——即根结点(没有前驱)
叶子:——即终端结点(没有后继)
森林:——指m棵不相交的树的集合(例如删除A后的子树个数)
有序树: ——结点各子树从左至右有序,不能互换(左为第一)
无序树:——结点各子树可互换位置。
双亲:——即上层的那个结点(直接前驱)
孩子:——即下层结点的子树的根(直接后继)
兄弟:——同一双亲下的同层结点(孩子之间互称兄弟)
堂兄弟:——即双亲位于同一层的结点(但并非同一双亲)
祖先:——即从根到该结点所经分支的所有结点
子孙:——即该结点下层子树中的任一结点
结点:——即树的数据元素
结点的度:——结点挂接的子树数(有几个直接后继就是几度,亦称“次数”)
结点的层次:——从根到该结点的层数(根结点算第一层)
终端结点:——即度为0的结点,即叶子
分支结点:——即度不为0的结点(也称为内部结点)
树的度:——所有结点度中的最大值(Max{各结点的度})
树的深度 (或高度):——指所有结点中最大的层数(Max{各结点的层次})
3. 逻辑结构
特点: 一对多(1:n)
除了根结点,其余结点都只有一个直接前驱,有多个直接后继,且子树之间互不相交。
4. 存储结构
树是非线性结构,仍然有顺序存储、链式存储等方式。
树的顺序存储方案可规定为:从上至下、从左至右将树的结点依次存入内存。
重大缺陷:复原困难(不能唯一复原就没有实用价值)。
树的链式存储方案可用多重链表:一个前趋指针,n个后继指针。
细节问题:树中结点的结构类型样式该如何设计?即应该设计成“等长”还是“不等长”?
缺点:等长结构太浪费(每个结点的度不一定相同);不等长结构太复杂(要定义好多种结构类型)。
解决思路:即把一般的树转换为二叉树---左孩子右兄弟的方法。研究最简单、最有规律的二叉树即可。
5. 树的运算
1. 普通树(即多叉树)若不转化为二叉树,则运算很难实现。需要把一般的树转换成二叉树。
2. 二叉树的运算仍然是插入、删除、修改、查找、排序等,但这些操作必须建立在对树结点能够“遍历”的基础上!
(遍历——指每个结点都被访问且仅访问一次,不遗漏不重复)。
二叉树
二叉树的结构最简单,规律性最强; 可以证明,所有有序树都能转为唯一对应的二叉树,不失一般性。(左孩子右兄弟表示法)
1. 二叉树的定义
定义:是n(n≥0)个结点的有限集合,由一个根结点以及两棵互不相交的、分别称为左子树和右子树的二叉树组成 。
逻辑结构: 一对二(1:2)
基本特征: ① 每个结点最多只有两棵子树(不存在度大于2的结点); ② 左子树和右子树次序不能颠倒(有序树)。
基本形态:
具有3个结点的二叉树可能有几种不同形态?5种 普通树呢?2种:后面四个都一样
二叉树的抽象数据类型定义
2. 二叉树的性质
第i层的结点数至多是多少? 至少有 1 个结点
性质1: 在二叉树的第i层上至多有个结点(i>0)。
归纳法证明:i=1时,至多有个结点 假设i-1层上至多有个结点数, ∵每个结点的度最多为2,所以,第i层上有*2个结点,即个结点。
深度为k的二叉树,至多有多少个结点? 至少有 k 个结点
性质2: 深度为k的二叉树至多有个结点(k>0)。
证明:根据性质1可知深度为k的二叉树至多有:
等比数列公式:
性质3: 对于任何一棵二叉树,若2度的结点数有n2个,则叶子数(n0)必定为n2+1 (即n0=n2+1)
满二叉树:一棵深度为k 且有个结点的二叉树。 (特点:每层都“充满”了结点)
在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上。
满二叉树的特点: ① 叶子只能出现在最下一层; ② 只有度为0和度为2的结点。
完全二叉树:对一棵具有n个结点的二叉树按层序编号,如果编号为i(1≤i≤n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中的位置完全相同。
在满二叉树中,从最后一个结点开始,连续去掉任意个结点,即是一棵完全二叉树。
完全二叉树的特点
1. 叶子结点只能出现在最下两层,且最下层的叶子结点都集中在二叉树的左部;
2. 完全二叉树中如果有度为1的结点,只可能有一个,且该结点只有左孩子。
3. 深度为k的完全二叉树在k-1层上一定是满二叉树。
对于完全二叉树,还特别具备以下2个性质:
性质4: 具有n个结点的完全二叉树的深度必为 +1, 是指不大于的一个整数
证明:根据性质2,深度为k的二叉树最多只有个结点,且完全二叉树的定义是与同深度的满二叉树前面编号相同,即它的总结点数n位于k层和k-1层满二叉树容量之间,即<n≤ 或≤n<
三边同时取对数,于是有:k-1≤<k 因为k是整数,所以k= +1
性质5: 对n个结点的完全二叉树,若从上至下、从左至右编号,则编号为i 的结点,其左孩子编号必为2i(2i>n无左孩子),其右孩子编号必为2i+1 (2i+1>n无右孩子) ;其双亲的编号必为 i/2 (i=1 时为根,除外)。
3. 二叉树的存储结构
顺序存储结构
二叉树的顺序存储结构就是用一维数组存储二叉树中的结点,并且结点的存储位置(下标)应能体现结点之间的逻辑关系——父子关系。
完全二叉树和满二叉树中结点的序号可以唯一地反映出结点之间的逻辑关系 。
完全二叉树的顺序存储
二叉树的顺序存储
一棵单枝树的顺序存储,需改造成完全二叉树形态,需增加很多空结点,造成存储空间的浪费。
二叉树的顺序存储结构一般仅存储完全二叉树
链式存储结构
用二叉链表即可方便表示。
一般从根结点开始存储。 (相应地,访问树中结点时也只能从根开始)
注:如果需要倒查某结点的双亲,可以再增加一个双亲域(直接前趋)指针,将二叉链表变成三叉链表。
二叉树结点数据类型定义
typedef struct node *tree_pointer;
typedef struct node {
int data;
tree_pointer left_child, right_child;
} node;
遍历二叉树和线索二叉树
详见:https://blog.csdn.net/qq1457346557/article/details/107213205
树和森林
详见:https://blog.csdn.net/qq1457346557/article/details/107213491
赫夫曼树及其应用
详见:https://blog.csdn.net/qq1457346557/article/details/107213838
代码实现:二叉树的应用https://blog.csdn.net/qq1457346557/article/details/107122992