#! /usr/bin/env python
# -*- coding: utf-8 -*-
'''
遍历推算
根据前序+中序/前序+后序/中序+后序重建二叉树
'''
import operator
pre_list_result = []
inorder_list_result = []
postorder_list_result = []
class Node:
def __init__(self, data, left, right):
self.data = data
self.left = left
self.right = right
def pre_travel(Node):
if Node:
# print(Node.data, end=',')
pre_list_result.append(Node.data)
pre_travel(Node.left)
pre_travel(Node.right)
def inorder_travel(Node):
if Node:
inorder_travel(Node.left)
# print(Node.data, end=',')
inorder_list_result.append(Node.data)
inorder_travel(Node.right)
def postorder_travel(Node):
if Node:
postorder_travel(Node.left)
postorder_travel(Node.right)
# print(Node.data, end=',')
postorder_list_result.append(Node.data)
def construct_tree(order_one, order_two, travel_type):
# 参数合法性判断
if len(order_one) == 0 | len(order_two) == 0:
return None
# 参数为前序和中序, 用来求后序
if "postorder" == travel_type:
# 前序遍历的第一个结点一定是根结点
root_data = order_one[0]
L = order_two.index(root_data)
# 递归构造左子树和右子树
left = construct_tree(order_one[1: 1 + L], order_two[:L], "postorder")
right = construct_tree(order_one[1 + L:], order_two[L + 1:], "postorder")
return Node(root_data, left, right)
# 参数为前序和后序, 用来求中序
elif "inorder_travel" == travel_type:
if not order_one:
return None
root_data = order_one[0]
if len(order_one) == 1:
return Node(root_data, None, None)
L = order_two.index(order_one[1]) + 1
# 递归构造左子树和右子树
left = construct_tree(order_one[1: 1 + L], order_two[:L], "inorder_travel")
right = construct_tree(order_one[1 + L:], order_two[L:-1], "inorder_travel")
if (L == 1):
if None != left and left.data > root_data:
right = Node(left.data, None, None)
left = None
if None != right and right.data < root_data:
left = Node(right.data, None, None)
right = None
return Node(root_data, left, right)
# 参数为中序和后序, 用来求前序
elif "pre_travel" == travel_type:
root_data = order_two[-1]
L = order_one.index(root_data)
# 递归构造左子树和右子树
left = construct_tree(order_one[:L], order_two[:L], "pre_travel")
right = construct_tree(order_one[L + 1:], order_two[L:-1], "pre_travel")
return Node(root_data, left, right)
else:
print("参数错误")
if __name__ == '__main__':
pre_list = [2169, 1049, 832, 56, 620, 974, 947, 1474, 1473, 1714, 1969, 2552, 2454, 2440, 2510, 3133, 2734, 2885,
3281, 3632]
inorder_list = [56, 620, 832, 947, 974, 1049, 1473, 1474, 1714, 1969, 2169, 2440, 2454, 2510, 2552, 2734, 2885,
3133, 3281, 3632]
postorder_list = [620, 56, 947, 974, 832, 1473, 1969, 1714, 1474, 1049, 2440, 2510, 2454, 2885, 2734, 3632, 3281,
3133, 2552, 2169]
# root = construct_tree(pre_list, inorder_list, "postorder")
# postorder_travel(root)
# print(postorder_list_result)
# print(operator.eq(postorder_list,postorder_list_result))
root = construct_tree(pre_list, postorder_list, "inorder_travel")
inorder_travel(root)
print(inorder_list_result)
print(operator.eq(inorder_list, inorder_list_result))
# root = construct_tree(inorder_list, postorder_list, "pre_travel")
# pre_travel(root)
# print(pre_list_result)
# print(operator.eq(pre_list, pre_list_result))
原理为前序的第一个节点即为根节点, 然后去中序遍历中找到根节点, 根节点的左边即为左子树的中序遍历, 右边即为右子树的中序遍历, 获取左子树的长度, 用它再去前序遍历中得到左子树和右子树的前序遍历。后序遍历和中序遍历同样如此,唯一的区别在于根节点在后序遍历中是最后一个元素。
与上述不同,略显复杂的为前序遍历和后序遍历构造二叉树,我们已知前序遍历的第一个节点为根节点,第二个节点为左子树的根节点,在后序遍历里获取左子树根节点的位置, 即可得到左子树的长度, 再依次递归即可,需要注意的是当子树的高度为1时,需要按照节点值判断, 是否需要进行左右子树互换,不然默认下单节点树的节点永远都是左儿子。