5.1.1 树的定义和基本术语
1.树的定义
在树中常常将数据元素称为结点。
树是n(n>=0)个结点的有限集合。当n=0时,称为空树;任意
(1)有且仅有一个特定的称为根;
(2)当n>1时,除根结点之外的其余结点被分成m(m>0)个互不相交的有限集合T1,T2,…,Tm,其中每个集合又是一棵树,并称为这个根结点的子树。
2.树的基本术语
结点的度、树的度
某结点所拥有的子树的个数称为该结点的度;树中各结点度的最大值称为该树的度。
叶子结点、分支结点
度为0的结点称为叶子结点,也称为终端结点;度不为0的结点称为分支结点,也称为非终端结点。
孩子结点、双亲结点、兄弟结点
某结点的子树的根结点称为该结点的孩子结点;反之,该结点称为其孩子结点的双亲结点;具有同一个双亲结点的孩子结点互称为兄弟结点。
路径、路径长度
如果数的结点序列n1,n2,、、、,nk满足如下关系:结点ni是结点ni+1d的双亲(1<=i<k),则把n1,n2,、、、,nk称为一条由n1至nk的路径;路径上经过的边数称为路径长度。在树中路径是唯一的。
祖先、子孙
如果从结点x到结点y有一条路径,那么x就称为y的祖先,y称为x的子孙。以某结点为根的子树中的任一结点都是该结点的子孙。
结点的层数、树的深度(高度)
规定结点的层数为1,对其余任何结点,若该结点在第k层,则其孩子结点在第k+1层;树中所有结点的最大层数称为树的深度,也称为树的高度。
层序编号
将树中结点按照从上层到下层、同层从左层到右层的次序依次给它们编以从1开始的连续自然数,树的这种编号方式称为层序编号。
有序树、无序树
如果一棵树中结点的各子树从左到右是有次序的,即若交换了结点各子树的相对位置,则构成不同的树,称这棵树为有序树;反之,称为无序树。
森林
m(m>=0)棵互不相交的树的集合构成森林。任何一棵树,删去根结点就变成了森林。
5.1.3 树的遍历操作
树的遍历是指从根结点出发,按照某种次序访问树中所有结点,使得每个结点被访问一次且仅被访问一次。
1.前序遍历
若树为空,则空操作返回;否则
(1) 访问根结点;
(2) 按照从左到右的顺序前序遍历根结点的每一棵子树。
2.后序遍历
若树为空,则空操作返回;否则
(1) 按照从左到右的顺序后序遍历根结点的每一棵子树。
(2) 访问根结点;
3.层序遍历(广度遍历)
从树的第一层(即根结点)开始,自上而下逐层遍历,在同一层中,按照
左到右的顺序对结点逐个访问。
5.2树的存储结构
5.2.1双亲表示法
5.3.1二叉树的定义
二叉树:是n(n≥0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两颗互不相交的、分别称为左子树和右子树的二叉树组成。
特点:①每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点;
②二叉树是有序的,其次序不能任意颠倒,即使树中的某个结点只有一颗子树,也要区分它是左子树还是右子树。
所以 二叉树和树是两种结构!
特殊二叉树
1. 斜树
所有结点都只有左子树的结点称为左斜树,所有结点都只有右子树的结点称为右斜树;左斜树和右斜树统称为斜树。
在斜树中,每一层只有一个结点,所以斜树的结点个数与其深度相同。
2.满二叉树
在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。
特点:①叶子只能出现在最下一层;
②只有度为0和度为2的结点。
3.完全二叉树
对一棵具有n个结点的二叉树按层序编号,如果编号为i(1≤i≤n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树。
(满二叉树从最右下角顺序的删除若干个结点)
特点:①叶子结点只能出现在最下两层,且最下层的叶子结点都集中在二叉树左侧连续的位置;
②如果与度为1的结点,只可能有一个,且该结点只能有左孩子;
③深度为k的完全二叉树在k-1层上一定是满二叉树;
④在同样结点个数的二叉树中,完全二叉树的深度最小。
5.3.2 二叉树的基本性质
性质5-1 二叉树的第i层上最多有2i-1个结点(i≥1)。
性质5-2 在一棵深度为k的二叉树中,最多有2k-1个结点,最少有k个结点。
性质5-3 在一棵二叉树中,如果叶子结点的个数为n0,度为2的结点个数为n2,则n0=n2+1。
性质5-4 具有n个结点的完全二叉树的深度为[log2n]+1。
性质5-5 对一棵具有n个结点的完全二叉树中的结点从1开始按层序编号,则对于任意的编号为i(1≤i≤n)的结点(简称为结点i),有:
(1) 双亲为i/2;
(2) 左孩子为2i;
(3) 右孩子为2i+1。
5.5 二叉树遍历的非递归算法
二叉树前序遍历的非递归算法:在前序遍历过某结点的整个左子树后,如何找到该结点的右子树的根指针。
解决办法:在访问完该结点后,将该结点的指针保存在栈中,以便以后能通过它找到该结点的右子树。
5.6 树、森林与二叉树的转换
树转换为二叉树
⑴加线——树中所有相邻兄弟之间加一条连线。
⑵去线——对树中的每个结点,只保留它与第一个孩子结点之间的连线,删去它与其它孩子结点之间的连线。
⑶层次调整——以根结点为轴心,将树顺时针转动一定的角度,使之层次分明。
森林转换为二叉树
⑴将森林中的每棵树转换成二叉树;
⑵从第二棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树根结点的右孩子,当所有二叉树连起来后,此时所得到的二叉树就是由森林转换得到的二叉树。
二叉树转换为树或森林
⑴加线——若某结点x是其双亲y的左孩子,则把结点x的右孩子、右孩子的右孩子、……,都与结点y用线连起来;
⑵去线——删去原二叉树中所有的双亲结点与右孩子结点的连线;
⑶层次调整——整理由⑴、⑵两步所得到的树或森林,使之层次分明。
5.7 哈夫曼树及哈夫曼编码
哈夫曼树:给定一组具有确定权值的叶子结点,带权路径长度最小的二叉树。
哈夫曼树应用——哈夫曼编码
前缀编码:一组编码中任一编码都不是其它任何一个编码的前缀。
前缀编码保证了在解码时不会有多种可能。