已知二叉树的前序中序,或是后序中序遍历,叫我们求出另一个遍历顺序的问题是很常见的。而解决这个问题的方法很多。在网上大多是利用左右子树的关系利用递归进行求解的。而我在这里想写一个非递归的简单方法。
一.求法简介
首先我们来看这样一个二叉树前序遍历: GDAFEMHZ 中序遍历: ADEFGHMZ。
我们想知道这颗树长什么样。
现在我提出一个想法:
我们先把中序遍历横着写一遍
A D E F G H M Z
接着我们从竖着方向上写前序遍历,就是按次序从高到低写下来。
A D E F G H M Z
G
D
A
F
E
M
H
Z
现在我们得到了这样一个二维的图。我们把图里的元素按照二叉树的连接方法连接起来
把它画的好看一点
这样我们就得到这颗二叉树了。也就可以知道其前序遍历前序遍历:GDAFEMHZ中序遍历:ADEFGHMZ后序遍历:AEFDHZMG。
还是这颗树,我们现在如果知道中序遍历中序遍历:ADEFGHMZ 和后序遍历:AEFDHZMG。
能不能求出其原来的树呢?
其实是可以的
还是一样的,第一步把中序遍历横着写下来
A D E F G H M Z
接着还是在竖直方向上我们把后序遍历倒过来按次序写
A D E F G H M Z
G
D
A
F
E
M
H
Z
这时我们就发现这两种方法一样了。
那么我知道前序和后序,能不能求解呢?
我们学习过二叉树之后就知道是不行的,这个方法肯定也是无法解决的。
那么可能有人要问为什么这么做是合理的?为什么前序遍历正着写,而后序遍历又是按逆序的呢?等等,接下来我会浅略证明一下。
二.证明
本人现在大一,机械专业,高考数学100出头,数学不是很好,所以只能简单证明一下,但大致能说清楚。
我们如果要画出二叉树,一种方法就是利用直角坐标系,确定元素的xy坐标。
如何确定xy坐标就是我们需要考虑的。
我们先来看二叉树的遍历特性。
前序遍历:
1.访问根节点
2.前序遍历左子树
3.前序遍历右子树
中序遍历:
1.中序遍历左子树
2.访问根节点
3.中序遍历右子树
后序遍历:
1.后序遍历左子树
2.后序遍历右子树
3.访问根节点
以前序遍历为例
我们现在有一个根节点,下一步如果有子节点的话,一定是访问子节点。而父节点到子节点,一定是向下走的,就是层数加一。也就是说,如果在一个最小子树集合中,他后面一个元素要么是他的子节点,要么是他的兄弟节点。也就是说,在最小子树中,前序的排法是三个方向上的合成
我们可以记为竖直方向上向下 i,水平方向上 向左j,向右-j。
那么同理分析中序,后序遍历
中序的一个最小子树中,中序遍历的顺序也是三个方向的合成:
竖直方向上有向下i,向上-i,水平方向向右-j
后序也是三个方向
竖直方向上有向上-i,水平方向向右-j向左j
对于前序遍历来说。一个最小子树中,顺序向后一位,i扩大一个单位,而j和-j比例系数不确定,不能判断扩大(缩小)多少个单位。
中序遍历顺序往后一位,-j扩大一个单位,而i和-i比例系数不确定,也不能判断扩大(缩小)多少个单位。
(实际上,这和解方程相似,如果只有一个未知量x,我们很轻易解出x=m中x的值,而如果有两个变量x,y并且只知道x>0,y<0,那么我们是无法解出x+y=m这个方程的。)
在数学上,如果我们有两组变量xy,mn,而且知道两组变量的关系,我们就能用一组变量来表示另一组。
现在我们知道前序遍历的顺序和i相关,而中序遍历的顺序和-j相关,那么我就可以用前序遍历的顺序来表示i,而中序遍历的顺序来表示-j,也就是前序遍历表示竖直方向,而中序遍历表示水平方向。
那么刚才的方法就很明了了。而后序遍历之所以要倒着写,就是因为他的顺序是和-i有关,正好是反过来的。如果你把中序遍历倒过来,后序遍历正过来,效果应该是一样的。
而且这样我们就知道了为什么只有前序和后序无法确定二叉树了,原因就是他们无法确定 j方向。
本人现在数学水平不佳,只能这样解释。如果数学好一些就可以补充 一些证明,或者如果有大佬知道更严谨的证明方法,我非常希望学习。代码层面水平有限,没有验证,也希望能向大佬学习。