假设我们现在知道一颗二叉树的中序遍历和后序遍历的结果,要怎么恢复这颗二叉树呢?
中序:3 4 8 6 7 5 2 1 10 9 11 15 13 14 12
后序:8 7 6 5 4 3 2 10 15 14 13 12 11 9 1
●第一轮:
我们知道后序遍历最后一个访问的是根节点,所以根节点就是1。
中序遍历的特点是根节点的左子树的元素都在根节点的左侧,右子树的元素都在根节点的右侧,从中序遍历序列我们可以划分成如下结构:
中序序列划分:
[3 4 8 6 7 5 2] 1 [ 10 9 11 15 13 14 12]
后序序列划分为:
[8 7 6 5 4 3 2] [10 15 14 13 12 11 9] 1
上面的序列划分中第一个括号里的都是左子树的元素,第二个括号一定都是右子树的元素。
后面我们将通过分析比较,前序遍历和中序遍历的左、右子树元素来恢复整棵二叉树的左、右子树。我们用中序遍历的左、右子树来概括二叉树的左、右子树。
1.图示:
●第二轮:
我们先看两个序列的第一个数组:
后序:[8 7 6 5 4 3 2] 中序:[3 4 8 6 7 5 2]
此时又可以利用上面的结论划分了:由后序遍历得出,根节点是2。然后根据2在中序中的位置可以划分为:
后序:[8 7 6 5 4 3 ]2
中序:[3 4 8 6 7 5 ]2
2.图示:
●第三轮:
继续划分,后序:[8 7 6 5 4 3] 中序:[3 4 8 6 7 5]
后序:[8 7 6 5 4 ]3 根节点为3
中序:3 [4 8 6 7 5]
3.图示:
●第四轮:
后序:[8 7 6 5 4] 中序:[4 8 6 7 5]
后序:[8 7 6 5 ] 4 根节点为4
中序:4 [8 6 7 5]
4.图示:
●第五轮:
后序:[8 7 6 5] 中序:[8 6 7 5]
后序:[8 7 6 ]5 根节点为5
中序:[8 6 7 ]5
5.图示:
●第六轮:
后序:[8 7 6 5] 中序:[8 6 7 5]
后序:[8 7] 6 根节点为6
中序:[ 8 ] 6 [ 7 ]
6.图示:
至此我们的左子树就全部恢复出来了,接下来我们分析一下右子树。
●第七轮:
后序:[10 15 14 13 12 11 9] 中序:[10 9 11 15 13 14 12]
后序:[10 15 14 13 12 11] 9 根节点为9
中序:[10] 9 [11 15 13 14 12] 再根据中序遍历的规则,我们一下就能确定出9 和10在右子树中的位置
7.图示:
●第八轮:
后序:[15 14 13 12 11] 中序:[11 15 13 14 12]
后序:[15 14 13 12]11 根节点为11
中序: 11 [15 13 14 12]
8.图示:
●第九轮:
后序:[15 14 13 12 ] 中序:[15 13 14 12]
后序:[15 14 13]12 根节点为12
中序: [15 13 14] 12
9.图示:
●第十轮:
后序:[15 14 13] 中序:[15 13 14]
后序:[15 14 ]13 根节点为13
中序: [15] 13 [14]
10.图示:
二叉树的恢复到这里就全部完成了,我们来看下完整的二叉树。
通过前序和后序也能恢复原始序列的,唯一的不同是前序序列的第一个是根节点,中序的处理也是上面一样的过程。感兴趣可以自己试一试。
前序:1 2 3 4 5 6 8 7 9 10 11 12 13 15 14
中序:3 4 8 6 7 5 2 1 10 9 11 15 13 14 12
后序:8 7 6 5 4 3 2 10 15 14 13 12 11 9 1
需要注意的是:根据前序和后序是不能恢复二叉树的。 根据上面的说明,我们通过前序可以知道根节点是1,通过后序也能知道根节点是1,但是中间是怎么划分的呢?其他元素哪些属于左子树,哪些属于右子树呢?很明显通过两个序列都不知道,所以前序和后序序列不能恢复二叉树。