第四章 树
(一) 树的基本概念
树是N(N≥0)个结点的有限集合,N=0时,称为空树,这是一种特殊情况。在任意一棵非空树中应满足:
1)有且仅有一个特定的称为根的结点。
2)当N>1时,其余结点可分为m(m>0)个互不相交的有限集合T1,T2,…,Tm,其中每一个集合本身又是一棵树,并且称为根结点的子树。
1 结点
-
根结点:树只有一个根结点
-
结点的度:结点拥有的子树的数量
2 树的度
树中所有结点的度数的最大值
3 结点关系
-
祖先结点:根结点到该结点的唯一路径上的任意结点
-
子孙结点
-
双亲结点:根结点到该结点的唯一路径上最接近该结点的结点
-
孩子结点
-
兄弟结点:有相同双亲结点的结点
4 层次、高度、深度、树的高度
-
层次:根为第一层,它的孩子为第二层,以此类推
-
结点的深度:根结点开始自顶向下累加
-
结点的高度:叶结点开始自底向上累加
-
树的高度(深度):树中结点的最大层数
5 树的性质
-
树中的结点数等于所有结点的度数加1
-
度为m的树中第i层上至多有mi−1个结点(i≥1)
-
高度为h的m叉树至多有(mh-1)/(m-1)个结点
-
具有n个结点的m叉树的最小高度为logm(n(m-1)+1)
(二) 树的存储结构
1 顺序存储结构
双亲表示法
用一组连续的存储空间存储树的结点,同时在每个结点中,用一个变量存储该结点的双亲结点在数组中的位置。
2 链式存储结构
孩子表示法
-
把每个结点的孩子结点排列起来存储成一个单链表。所以n个结点就有n个链表;
-
如果是叶子结点,那这个结点的孩子单链表就是空的;
-
然后n个单链表的的头指针又存储在一个顺序表(数组)中。
需要设计两种结点结构类型:一是孩子链表的孩子结点,二是每个孩子链表的表头结点(存在数组中)
孩子兄弟表示法
顾名思义就是要存储孩子和孩子结点的兄弟,具体来说,就是设置两个指针,分别指向该结点的第一个孩子结点和这个孩子结点的右兄弟结点。
(三) 二叉树
二叉树是n(n≥0)个结点的有限集合:
-
或者为空二叉树,即n=0。
-
或者由一个根结点和两个互不相交的被称为根的左子树和右子树组成。左子树和右子树又分别是一棵二叉树。
1 二叉树的五种基本形态
-
空树
-
只有一个根结点
-
根结点只有左子树
-
根结点只有右子树
-
根结点既有左子树又有右子树
2 特殊二叉树
-
斜树:每一层都只有一个结点,结点数与树的深度相同
-
满二叉树:1)分支结点都存在左子树和右子树;2)叶子都在同一层,特点:非叶子结点的度一定是2;相同深度二叉树中满二叉树的结点个数最多,叶子树最多
-
完全二叉树
3 二叉树的性质
-
非空二叉树上叶子结点数等于度为2的结点数加1
-
非空二叉树上第K层上至多有2k−1个结点(K≥1)
-
高度为H的二叉树至多有2H-1个结点(H≥1)
(四) 二叉树的存储结构
1 顺序存储
二叉树的顺序存储结构就是用一组地址连续的存储单元依次自上而下、自左至右存储完全二叉树上的结点元素。
2 链式存储
二叉树每个结点最多两个孩子,所以设计二叉树的结点结构时考虑两个指针指向该结点的两个孩子。
这种结构的链表由于有两个指针,所以叫二叉链表。
另外还可以增加指针指向该结点的双亲结点,那这时三个指针的链表就叫三叉链表。
(五) 二叉树的遍历(递归)
二叉树的遍历是指按某种次序依次访问树中的每个结点,使得每个结点均被访问一次,而且仅被访问一次
1 递归先序遍历
如果二叉树为空,什么也不做。否则:
1)访问根结点;
2)先序遍历左子树;
3)先序遍历右子树。
2 递归中序遍历
如果二叉树为空,什么也不做。否则:
1)中序遍历左子树;
2)访问根结点;
3)中序遍历右子树。
3 递归后序遍历
如果二叉树为空,什么也不做。否则:
1)后序遍历左子树;
2)后序遍历右子树;
3)访问根结点。
(六) 二叉树的遍历(非递归)
1 层次遍历
若树为空,则什么都不做直接返回。否则:
从树的第一层开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。
(七) 线索二叉树
N个结点的二叉链表,每个结点都有指向左右孩子的结点指针,所以一共有2N个指针,而N个结点的二叉树一共有N-1条分支,也就是说存在2N-(N-1)=N+1个空指针。
1 线索二叉树的定义
指向前驱和后继的指针称为线索,加上线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树
对二叉树以某种次序遍历使其变为线索二叉树的过程就叫做线索化
(八) 哈夫曼树和哈夫曼编码
1 哈夫曼树的概念
权
树中结点相关的数值
路径长度
从树中某结点到另外一个结点之间的分支数目(经过的边数)
带权路径长度
从树的根结点到任意结点的路径长度(经过的边数)与该结点上权值的乘积称为该结点的带权路径长度
树中所有叶结点的带权路径长度之和称为该树的带权路径长度
W P L = ∑ i = 1 n w i × l i WPL = \sum_{i = 1}^{n}{w_{i} \times l_{i}} WPL=i=1∑nwi×li
wi是第i个叶结点所带的权值;li是该叶结点到根结点的路径长度
2 哈夫曼树的算法
-
将这N个结点分别作为N棵仅含一个结点的二叉树,构成森林F。
-
构造一个新结点,并从F中选取两棵根结点权值最小的树作为新结点的左、右子树,并且将新结点的权值置为左、右子树上根结点的权值之和。
-
从F中删除刚才选出的两棵树,同时将新得到的树加入F中。
-
重复步骤2)和3),直至F中只剩下一棵树为止。
注意:
-
每个初始结点最终都成为叶结点,并且权值越小的结点到根结点的路径长度越大。
-
构造过程中共新建了N-1个结点(双分支结点),因此哈夫曼树中结点总数为2N-1。
-
每次构造都选择2棵树作为新结点的孩子,因此哈夫曼树中不存在度为1的结点