最近在学习二叉树,遇到了这样一题,在这里给大家提供一种方法,可能不是最好的,仅供大家参考和相互交流学习。
已知一个二叉树前序遍历、中序遍历的结果,请确定该二叉树并输出其后序遍历的结果。
例如: 先序遍历结果为:A B D E G C F H;
中序遍历结果为:D B G E A C H F;
则应该能够得出后序遍历结果为:D G E B H F C A。
分析这个问题,我们可以从先序、中序、后序遍历的特点和结果,结合题目中给出的典型例子,得出相关的规律;
我的思路是:先由先序和中序遍历结果计算得到二叉树,之后用递归方法对二叉树进行后序遍历得出结果。
(1)首先,由先序和中序遍历,我们是完全可以得到二叉树的构成的,这由两者的区别和联系所共同决定;
我们以上面的例子来说明思路:
① A B D E G C F H 可以被分成两个部分来看 A B D E G and C F H
② D B G E A C H F D B G E A C H F
以先序遍历为基础,我们知道先序遍历一定先遍历根节点,由①可知 A 一定是根节点,则在先序和中序遍
历过程中,两者都要先遍历完 A 的左子树,再去遍历 A 的右子树;所以,很明显地,在中序遍历中,A 将会
列表分为两半:D,B,G,E 以及 C,H,F。其中 D,B,G,E 均为 A 的左子树节点,而 C,H,F 均为 A 的右子树的
节点。
我们将视线转回先序遍历,由于遍历根节点 A 之后,紧接着按照先序遍历一定会去遍历A的左子树的根节
点,即节点B;又因为 B,D,E,G 均为 A 的左子树节点,根据先序遍历的特点,在 A 的左子树遍历完成之后,
立刻就会去遍历 A 的右子树的根节点,也就是第二个部分中①的第一个节点 C(应注意②中的第二部分第一个节
点也为C仅仅是这一题的情况,不能由此断言A的右子树根节点为C,而应根据先序遍历的首位C来判断)。
这样,我们就可以将原有的整个二叉树,在除去根节点 A 之后,得到它的两个子树及其各自的根节点 B
和 C,而下面的思路就很明了,使用递归方法,分别对B、C两个子树进行左右分解,注意判断递归条件和不断
建立新节点,这样就可以获取整个二叉树了。
再递归函数中,分情况讨论可以分为以下几种:
1)A B D E G C F H
D B G E A C H F (完整类型)
2)A C F H
A C H F (A不含有左子树)
3)A B D E G
D B G E A (A不含有右子树)
4)A
A (A不含有左右子树,即A为叶节点)
(2)在获取整个二叉树后,使用递归方法写后序遍历函数,对二叉树进行后序遍历,即可得到正确结果。
示例代码如下:
def tree_establish(Node, Preorder, Inorder, n): # 建立二叉树(Node为根节点,n为节点数量)
i = Inorder.index(Preorder[0])
if i == 0: # 根节点 A 不存在左子树
if i + 1 <= n - 1: # 根节点 A 存在右子树(C为根节点)
Node.rchild = node(Preorder[i+1])
tree_establish(Node.rchild, Preorder[i+1:n:1], Inorder[i+1:n:1], n-1)
else: # 根节点A不存在左右节点(子树)
return 1
else: # 根节点 A 存在左子树(B为根节点)
if i + 1 <= n - 1: # 根节点 A 含有左右子树
Node.lchild = node(Preorder[1])
Node.rchild = node(Preorder[i+1])
tree_establish(Node.lchild, Preorder[1:i+1:1], Inorder[0:i:1], i)
tree_establish(Node.rchild, Preorder[i+1:n:1], Inorder[i+1:n:1], n-i-1)
else: # 根节点 A 不含有右子树
Node.lchild = node(Preorder[1])
tree_establish(Node.lchild, Preorder[1:i+1:1], Inorder[0:i:1], i)
def post_order_probing(Node): # 后序遍历函数(递归实现)
if Node is None:
return 0
else:
if Node.lchild:
post_order_probing(Node.lchild)
if Node.rchild:
post_order_probing(Node.rchild)
print(Node.elem, end=' ')
class node(object): # 定义节点类
def __init__(self, elem=None, lchild=None, rchild=None, par=None):
self.elem = elem
self.lchild = lchild
self.rchild = rchild
self.par = par
class tree(object): # 定义树类
def __init__(self, root=node()):
self.root = root
preorder = [i for i in input().split()] # 输入先序遍历结果
inorder = [i for i in input().split()] # 输入中序遍历结果
N = len(preorder)
MyTree = tree(node(preorder[0])) # 初始化二叉树
tree_establish(MyTree.root, preorder, inorder, N) # 建立二叉树
post_order_probing(MyTree.root) # 打印后序遍历结果(最后有个空格)