1. 树概念
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合,有二叉树,N叉树等等。
- 子树是互不相交的(比如B不能连接C,D不能连接E)
- 除了根节点外,每个节点有且只有一个父节点。(A是B、C、D、E的父节点,B是F、G的父节点)
- 一颗有N个节点的树,有N-1条边。 (下图有10个节点,9条边)
在树结构中,度是指一个节点的子节点个数的最大值。如果一个节点没有子节点,则其度为0;如果一个节点只有一个子节点,则其度为1;如果一个节点有两个子节点,则其度为2,以此类推。【二叉树不存在度大于2的节点,上图是个N叉树】
- 结点的度:一个结点含有子树的个数称为该结点的度; 如上图:A的度为4,B的度为2,F的度为0
- 树的度:一棵树中,所有结点度的最大值称为树的度; 如上图:树的度为4
- 叶子结点或终端结点:度为0的结点称为叶结点; 如上图:C、F、G、H、等节点为叶结点
- 双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:A是B的父结点,B是F的父节点,同样也是G的父节点。
- 孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点; 如上图:B是A的孩子结点,C是A的孩子节点…
- 根结点:一棵树中,没有父结点的结点;如上图:A
- 结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推。上图树的层次是3层
- 树的高度或深度:树中结点的最大层次; 如上图:树的高度为3
- 非终端结点或分支结点:度不为0的结点; 如上图:B、D、E…等节点为分支结点
- 兄弟结点:具有相同父结点的结点互称为兄弟结点; 如上图:B、C是兄弟结点,共同的父节点是A
- 堂兄弟结点:在同一层的结点互为堂兄弟;如上图:G、H互为兄弟结点
- 结点的祖先:从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先,B是F的祖先
- 子孙:以某结点为根的子树中任一结点都称为该结点的子孙。如上图:所有结点都是A的子孙
- 森林:由m(m>=0)棵互不相交的树组成的集合称为森林
2.二叉树的概念
二叉树是一种树形结构,其中每个节点最多有两个子节点。 二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。
-
二叉树有左右之分,次序不能颠倒,因此二叉树是有序树。如上图,从上到下,从左往右,依次为1、2、3、4、5、6。所谓有序是指从左往
-
. **满二叉树: 一棵二叉树,如果每层的结点数都达到最大值,则这棵二叉树就是满二叉树。**也就是说,如果一棵 二叉树的层数为K,且结点总数是
2 k − 1 2^k-1 2k−1
,则它就是满二叉树。 -
完全二叉树: 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n 个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从0至n-1的结点一一对应时称之为完 全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。
1.2二叉树的性质
-
若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1)(i>0)个结点
-
若规定只有根结点的二叉树的深度为1,则深度为K的二叉树的最大结点数是
2 k − 1 2^k-1 2k−1
(k>=0) -
对任何一棵二叉树, **如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1,**也就是叶子节点比非叶子节点多1个。
-
具有n个结点的完全二叉树的深度K为
l o g 2 ( n + 1 ) log2(n+1) log2(n+1)
上取整。- 根据第二点性质可以推导出,2^k -1= n --> 2^k = n+1,这个k就等于第4点中提到的k,因为k为log2(n+1);那么也就是求2的多少次方等于k,假设有9个节点,9+1 等于10,2的3次方等于8,2的4次方等于16,向上取整就是取4。该二叉树深度为4。
-
对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i 的结点有:
- 若i>0,双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点【知道孩子序号,求父节点】
- 若2i+1<N,左孩子序号:2i+1,否则无左孩子
- 若2i+2<n,右孩子序号:2i+2,否则无右孩子。
3.二叉树遍历
二叉树的遍历是指从根节点出发,按照某种次序依次访问二叉树中的所有节点,使每个节点被且仅被访问一次。二叉树的遍历方式主要有:先序遍历、中序遍历、后序遍历、层次遍历。
- 先序遍历:根节点 -> 左子树 -> 右子树
- 中序遍历:左子树 -> 根节点 -> 右子树
- 后序遍历:左子树 -> 右子树 -> 根节点
- 层次遍历:按照从上到下顺序访问每个节点
3.2前序遍历
先序遍历:根节点 -> 左子树 -> 右子树,依次打印节点
遍历结果:1、2、 4 、 5、 3 、6
首先访问根节点1,打印1,然后递归地访问左子树和右子树。在左子树中,打印2,站在节点2的视角,也是一棵二叉树,节点2是这棵二叉树的根节点,于是又要先访问节点2的左子树,打印4,站在节点4的角度,节点4是根节点,节点4也有左子树和右子树,于是又要再去访问节点4的左子树,4的左子树为空,递归回来,访问节点4的右子树,右子树为空,递归回来。然后访问节点2的右子树;
递归回来,此时站在根节点1的视角,它的左子树遍历完了,于是访问右子树,站在右子树的视角,它此时也是一个独立 的二叉树,打印3后,于是要访问节点3的左子树和右子树。
以此类推,如下图,因此每个节点可以当做是一个二叉树,由多个小的二叉树结合成一个大的二叉树。
3.2 中序遍历
中序遍历:左子树 -> 根节点 -> 右子树依次打印节点
遍历结果:4、 2 、5、 1、6、3
**还是一样的图,只是访问的根节点的时机不一样!前序遍历,先打印根节点,中序遍历先打印最左的一个节点,后续遍历,最后打印根节点!**进来先访问到了根节点1,不打印,直到把左子树走完,此时遍历到了节点4,4没有左子树,于是递归回来打印4,4没有右子树,递归回来打印2,只有把节点2的左子树遍历完后,才会打印2;依次类推。所以只有把每个节点的左子树遍历完,才会打印当前节点,然后再去遍历右子树,右子树也有它的左子树,同理。
3.3 后序遍历
后序遍历:左子树 -> 右子树 -> 根节点
遍历结果:4、 5、 2、 6、 3、 1
根据前中后序遍历,得出,后序遍历,只有当左子树和右子树遍历完,才会回来打印根节点。
遍历开始,遇到1,不能打印,只有把1的左子树和右子树遍历完才能打印1,
走到节点2,不能打印,要先把节点2的左子树和右子树遍历完才能打印2,
走到4,由于4的左子树和右子树为空,递归回来打印4,
走到5,由于5的左子树和右子树为空,递归回来打印5,
此时再递归回来就可以打印节点2了,因为2的左子树和右子树都遍历完了。
依次类推,最后才能打印根节点1。
- 得出一个规律:前序遍历的第一个打印的节点肯定是根节点,后序遍历最后打印的节点肯定是根节点。【重点】
根据上述规律,做出这道题:
1.设一课二叉树的中序遍历序列:badce,后序遍历序列:bdeca,则二叉树前序遍历序列为()
A: adbce B: decab C: debac D: abcde
根据规律可以画出如下图:
根据后序遍历,最后一个打印的节点是a,那么a肯定就是这颗二叉树的根节点,再根据中序遍历,按照a的位置,划分左右子树,a的左边是a的左子树,a的右边是a的右子树,由于a的右边有多个节点,不确定哪个节点是a的孩子节点,所以要继续化简,于是得出:
再根据后序遍历的倒数第二个节点,因为后序遍历中的a已经被刨除出去了,所以当前后序遍历的最后一个节点是c,再根据规律后序遍历的最后一个节点肯定是根节点,按照c的位置,划分出中序遍历的左右子树,在中序遍历中,c的左边是c的左子树,c的右边是c的右子树,由于c的左右皆剩下1个节点,那么这两个节点就是c的孩子节点,于是得出:
,因为后序遍历中的a已经被刨除出去了,所以当前后序遍历的最后一个节点是c,再根据规律后序遍历的最后一个节点肯定是根节点,按照c的位置,划分出中序遍历的左右子树,在中序遍历中,c的左边是c的左子树,c的右边是c的右子树,由于c的左右皆剩下1个节点,那么这两个节点就是c的孩子节点,于是得出:
答案是:D