树是n个结点的有限集,当n = 0时,称为空树
非空树应满足以下条件
有且仅有一个特定的结点,称为根,没有直接前驱,有零个或多个直接后继;
其余n-1个结点可以划分成m个互不相交的有限集,每个有限集又是一棵树,称为根的子树。每颗子树的根节点有且仅有一个直接前驱,但有零个或多个直接后继
结点:包含一个数据元素及若干指向其子树的分支
结点的度:结点拥有的子树个数
树的度:树内各节点的度的最大值
叶子:度为0的结点,也叫终端结点;
非终端结点与分支结点:度不为0的结点。除根结点外的分支结点称为内部结点
孩子:结点的子树的根称为该结点的孩子
双亲:该结点称为孩子的双亲
兄弟:同一双亲孩子之间称为兄弟
双亲在同一层的结点之间称为堂兄弟
路径,路径长度:路径指从根节点到任意结点所经过的结点的集合,且每一个都是后一个的后继,即均是不同层,最短下降的。路径长度为路径所通过的结点数目-1。
结点的层次:从根节点开始定义为第一层,以此类推。
深度:层次的最大层。
定义
每个结点的度不大于2;
每个结点的孩子结点次序不能任意颠倒,因此树的孩子有左孩子和右孩子之分
满二叉树↑
性质:
- 二叉树的第i层上至多有2^(i-1)个结点;度为m的树第i层上至多有m^(i-1)个结点
- 深度为k的二叉树至多有2^k-1个结点;深度为k的m叉树最多有m^k-1/m-1个结点
- 对任意一棵二叉树,若终端结点数为n0,度为2的结点数位n2,则n0 = n2+1
- 具有n个结点的完全二叉树的深度为K = (log2n)向下取整+1或(log2(n+1))向上取整
- 对于完全二叉树中编号为i的结点:
- i = 1,结点是二叉树的根
- i > 1,双亲编号为(i/2)向下取整;
- i为偶数时,是双亲结点的左孩子。双亲结点编号为i/2,,
- i为奇数时,是双亲结点的右孩子。双亲结点的编号为(i-1)/2
- 编号为i的结点的左孩子编号为2i,右孩子为2i+1
- n为节点数,2i>n,i无左孩子;2i+1>n无右孩子
- n为节点数
- 为奇数则为每个结点都儿女双全
- 为偶数则编号最大的分支结点只有左孩子
顺序存储和链式存储
按结点编号存在一个数组中,数组中下标位置为i-1
一般二叉树顺序存储:完全对照结点编号和下标顺序存储;
最坏情况下深度为k的右单支二叉树需2^k-1个存储空间
递归实现
先序遍历
访问结点->先序遍历左孩子->先序遍历右孩子中序遍历
中序遍历左孩子->访问结点->中序遍历右孩子后续遍历
后续遍历左孩子->后续遍历右孩子->访问结点
中序遍历的结果和先序、后序遍历的结果可以还原出一棵二叉树;但先序、后序遍历的结果并不能还原出二叉树
如何求输出的序列?
从根结点开始从左到右画线,每次通过结点记为一次通过;画完一圈每个结点会有三次通过,先序就是第一次通过时,输出结点内容;中序就是第二次通过时,输出结点内容;后序就是第三次通过时,输出结点内容。注意在终末结点应该踏步两次表示完成该结点的左右孩子遍历。
为了增大空间利用率,当没有左孩子时,储存指向其前驱的指针;当没有右孩子时,储存指向其后继的指针,且多存两个tag,0时表示存储左孩子,1时表示存储的是前后继。
前后继的确定:先将二叉树按先中后的遍历方式输出,即可知道每个结点的前后继。若无前驱或后继,则指向NULL
访问二叉树找指定结点的前驱或后继
用一组连续的空间来存储书中的节点,在保存每个节点的同时附设一个指针来指示其双亲结点在表中的位置
DATA|Parent
以数组的形式存储;
优点:快速找到妈;
缺点:不好找孩子;
方案1、指针域的个数就等于树的度,树的度是树各个节点度的最大值
空链域个数S=nk-(n-1) = n(k-1)+1 //k度,n个节点
方案2、使每个结点的指针域的个数等于该结点的度。专门取一个位置来存放指针域的个数
人话:按存的孩子数分配存储空间
由于各个节点的链表是不同的结构,加上要维护节点的度的数值,在运算上会带来时间上的损耗
方案3、孩子链表法
把每个节点的孩子结点排列起来,形成一个单链表,称为孩子链表。n个结点工业n个孩子链表(叶子结点的孩子链表为空表),而n个节点的数据和n个孩子链表的头指针又组成一个顺序表
存储结构与二叉树类似,便于实现树的各种操作
- 在所有相邻兄弟结点间加一水平连线
- 对每个非叶节点k,除了其最左边的孩子结点外,删去k与其他孩子节点的连线。
- 所有水平线以左边节点为轴心顺时针旋转45度(……?),使之结构层次分明
森林也可以方便的用孩子兄弟链表。
将一棵二叉树还原为树或森林。
若树非空,则遍历方法:
等同于转换的二叉树进行先序遍历
若树非空,则遍历方法为:
等同于转换的二叉树进行中序遍历
以上图为例,此时遍历的序列:EBHFGCDA
若森林非空,则遍历方法为:
当森林非空,则遍历方法为
根据树的先根遍历和后根遍历序列还原树?
观察,成组的,先划分,先根遍历序列每一组的第一个和后根遍历序列每组的最后一个是相同的!且这个元素是该组的根结点。再继而进行分组,找对应。
根据森林的先、中遍历序列还原森林?
观察,同样的找分组,第一次找到的分组有几个就有几棵树,之后根据之前的原则还原即可
路径长度:
从一个节点到另一个节点需要走几步
带权路径长度:
给每个路径加上权重
设二叉树具有n个带权值的叶子节点,那么从根节点到各个叶子节点的路径长度与相应节点权值的乘积的和,叫做二叉树的带权路径长度
具有最小带权路径长度的二叉树称为哈夫曼树
只要叶子权重固定,就有固定的最优二叉树,带权路径长度最短,称为哈夫曼树。
给定权值w=(1,3,5,7)构造一棵哈夫曼树
每次取权值最小的根节点,和为父节点,以此构造。
编码
如何编码让电文的长度越短越好?