第七章 解决二叉树的编程问题
二叉树是n(≥0)个有限元素的集合,该集合或者为空,或者由一个称为根的元素及两个不相交的,被称为左子树和右子树的二叉树组成。当集合为空时,称该二叉树为空二叉树,在二叉树中一个元素也称为一个结点。
二叉树是有序的,即将其左右子树颠倒,就成为另一个不同的二叉树。
结点的度,结点所拥有的子树的个数
叶结点,度为0的结点,也称为终端结点
分支节点,度不为0的结点,也称为非终端结点
孩子、兄弟、双亲结点,树中一个结点的子树的根节点称为这个结点的孩子。这个结点称为孩子的双亲,具有同一个的双亲的孩子结点互称为兄弟结点。
路径、路径长度,如果一棵树的一串结点n1,n2,……,nk有如下关系:结点ni是ni+1的父结点(1≤i≤k),就把n1,n2,……,nk称为一条由n1至nk的路径。这条路径的长度是k-1
祖先、子孙。在树中,如果有一条路径从结点M到结点N,那么M就称为N结点的祖先,而N称为M的子孙。
结点的层数。规定树的根结点的层数为1,其余结点的层数等于它的双亲结点的层数加1。
树的深度。树中所有结点的层数的最大值称为该树的深度。
满二叉树,在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子结点都在同一层上,这样的一棵二叉树称为满二叉树。
完全二叉树,一棵树深度为k的有n个结点的二叉树,对树中的结点按从上至下,从左至右的书序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵树称为完全二叉树。完全二叉树的特点是:叶子结点只能出现在最下层和次下层,且最下层的叶子节点集中在树的左部。显然一棵满二叉树必定是完全二叉树,反之,则不然。
二叉树的性质:
1) 一棵非空二叉树的第i层最多有2i-1个结点(i≥1)
2) 一棵深度为k的二叉树中,最大具有2k-1个结点
3) 对于一棵非空的二叉树,如果叶子结点数为n0,度为2的结点数为n2,则有:
n0=n2+1
4) 具有n个结点的完全二叉树的深度k为[log2n]+1。
5) 对于具有n个结点的完全二叉树,如果按照从上到下和从左到右的顺序对二叉树中的所有结点从1开始进行编号,则对于任意序号为i的结点有:
- 如果i>1,则序号为i的结点的双亲结点的序号为i/2(整除);如果i=1,则序号为i的结点是根结点,无双亲结点。
- 如果2i≤n,则序号为i的结点的左孩子结点的序号为2i;如果2i>n,则序号为i的结点无左孩子
- 如果2i+1≤n,则序号为i的结点的右孩子结点的序号为2i+1;如果2i+1>n,则序号为i的结点无右孩子
- 此外,若对二叉树的根结点从0开始编号,则相应的i号结点的双亲结点的编号为(i-1)/2,左孩子的编号为2i+1,右孩子的编号为2i+2
二叉树的顺序存储:用一组连续的存储单元存放二叉树中的结点,完全二叉树和满二叉树用顺序存储比较合适
二叉树链式存储:用链表来表示一棵二叉树,即用链表来指示这元素的逻辑关系。
1) 二叉链表存储:数据域、指向左右孩子所在的链结点的存储地址,如下图:
2) 三叉链表存储:最后加一个指向双亲结点的指针域,如下图:
二叉树遍历方法:
1) 先序遍历:
- 若二叉树为空,遍历结束,否则
- 访问根结点
- 先序遍历根结点左子树
- 先序遍历根结点右子树
2) 中序遍历
- 若二叉树为空,遍历结束。否则,
- 中序遍历根结点的左子树
- 访问根结点
- 中序遍历根结点右子树
3) 后序遍历
- 若二叉树为空,遍历结束。否则,
- 后序遍历根结点的左子树
- 后序遍历根结点的右子树
- 访问根结点
4) 层次遍历
从二叉树的第一层(根结点)开始,从上至下逐层遍历,在同一层中,则按从左至右的顺序对结点逐个访问。
基本思想是:由于层次遍历结点的顺序是先遇到的结点先访问,与队列操作的顺序相同。所以,在进行层次遍历时,设置一个队列,将根节点引入队,当队列非空时,循环执行以下三步:
(1) 从队列中取出一个结点引用,并访问该结点
(2) 若该结点的左子树非空,将该结点的左子树引用入队
(3) 若该结点的右子树非空,则将该结点的右子树引用入队
各种遍历算法示例如下:
最优二叉树——哈夫曼树
最优二叉树,也称哈夫曼树,是指对于一组带有确定权值的叶节点,构造的具有最小带权路径长度的二叉树。
二叉树的路径长度是指由根结点到所有叶节点的路径长度之和
如果二叉树中的叶子结点带有一定的权值,二叉树的路径的长度可以推广为:从根结点到各个叶节点的路径长度与相应叶节点权值的乘积之和(记为WPL)。
构造哈夫曼树的思路:根据哈夫曼树的定义,要使其WPL值最小,必须使权值最大叶结点越远离根结点。
算法描述:
1) 给定n个权值{W1,W2…… Wn}构造n棵只有一个叶子结点的二叉树,从而得到一个二叉树的集合F={T1,T2,……Tn};
2) 在F中选取根结点的权值最小和次小的两棵树作为左右子树构造一棵新的二叉树,这课二叉树根结点的权值为其左右子树根结点权值之和
3) 在集合F中删除作为左右子树的两棵二叉树,并将新建立的二叉树加入到集合F中;
4) 重复2)、3)两步,当F中只剩下一棵二叉树时,这课二叉树便是所要建立的哈夫曼树。
例子: