Python实现:给定二叉树的先序遍历和中序遍历结果,确定该二叉树的后序遍历结果

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/Ocean_waver/article/details/89461509
最近在学习二叉树,遇到了这样一题,在这里给大家提供一种方法,可能不是最好的,仅供大家参考和相互交流学习。

    已知一个二叉树前序遍历、中序遍历的结果,请确定该二叉树并输出其后序遍历的结果。
例如:        先序遍历结果为: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)                    # 打印后序遍历结果(最后有个空格) 

猜你喜欢

转载自blog.csdn.net/Ocean_waver/article/details/89461509