史上完美解析——已知中序后序遍历,求二叉树先序遍历

目录

前言

题解代码

核心点解析

验证

总结



前言

数据结构,树,递归是其核心;


题解代码

对于该题的解答,给出python代码如下(后续补充Java和C):

文件名为:for_preorder.py

res = []


def preorder_from_in_and_post(inorder, postorder):
    if len(inorder) == len(postorder) == 1:
        res.append(inorder[0])
    if len(inorder) == len(postorder) == 2:
        res.append(postorder[-1])
        res.append(postorder[0])
    if len(inorder) == len(postorder) >= 3:
        head = postorder[-1]
        idx = inorder.index(head)
        res.append(head)
        preorder_from_in_and_post(inorder[0:idx], postorder[0:idx])
        preorder_from_in_and_post(inorder[idx + 1:], postorder[idx:-1])


# preorder_from_in_and_post(
#     [200, 323, 990, 463, 154, 673, 927, 703, 873, 174, 473, 997, 983, 460, 85, 513, 56, 416, 981, 563],
#     [200, 323, 463, 154, 990, 673, 703, 174, 873, 983, 997, 473, 85, 513, 416, 563, 981, 56, 460, 927])
# print('{} {}'.format('先序:', res))
# 中序:200, 323, 990, 463, 154, 673, 927, 703, 873, 174, 473, 997, 983, 460, 85, 513, 56, 416, 981, 563
# 后序:200, 323, 463, 154, 990, 673, 703, 174, 873, 983, 997, 473, 85, 513, 416, 563, 981, 56, 460, 927
# 先序:927, 673, 990, 323, 200, 154, 463, 460, 473, 873, 703, 174, 997, 983, 56, 513, 85, 981, 416, 563

核心点解析

1.后序遍历的最后一个数字,是整棵树的头节点head;
2.以head切割中序遍历,head左边序列必定为左子树,head右边序列必定为右子树;
3.先序遍历顺序:头 -> 左 -> 右;
4.递归含义/函数含义:找出当前序列的头节点;
5.将目标序列(中序,后序)传进递归函数,目标序列将被分成2个子序列,即左子树和右子树
    此时,将左子树先传进递归函数,再将右子树传进递归函数;
    变成了,求2个子树序列的头节点;
    大规模问题,借由递归,变成一个个子问题,子问题的解决变得越来越简单;
6.由于左子树先进入递归函数,右子树后进入递归函数,并且递归前,已经获取当前头节点;
    所以天然符合,头 -> 左 -> 右的顺序;即先序;

    此时,无论是直接打印,还是先存入列表,最后都可以得到目标序列的先序遍历;

验证

接下来是验证:

1.对数器验证:
    此处使用的对数器逻辑是:用代码构造二叉树(构造的树可能是完全二叉树,也可能不是),利用正常的递归逻辑获取中序/后序/先序遍历;
    将上一个步骤的中序/后序遍历传入解答代码中,得出先序遍历,并和上一步骤的先序遍历,进行对比;

2.二叉树构造代码(文件名为:create_tree.py):

import random


class TreeNode:
    def __init__(self):
        self.data = None
        self.left = None
        self.right = None
        
# 树生成伪代码:
# init head
# insert head into stack: target
# candidates = new stack: target
# while length(node_data) > 0:
# 	while stack: target.length > 0:
# 		node = stack: target.pop()
# 		node.data = node_data.pop()
# 		node.left = new TreeNode
# 		node.right = new TreeNode
# 		insert node.left into candidates
# 		insert node.right into candidates
# 	stack: target = candidates	#随机取candidates中的元素
# 	candidates = new stack: target


# 构造对数器

def createTree(head):
    node_data = random.sample(list(range(1, 1001)), 20)
    target = [head]
    candidates = []
    while len(node_data) > 0:
        while len(target) > 0:
            node = target.pop()
            node.data = node_data.pop()
            if len(node_data) == 0:
                break
            node.left = TreeNode()
            node.right = TreeNode()
            candidates.append(node.left)
            candidates.append(node.right)
        target = random.sample(candidates, round(random.uniform(0.75, 1) * len(candidates)))
        candidates.clear()


inorder = []
postorder = []
preorder = []


def get_inorder(head):
    if head and head.left:
        get_inorder(head.left)
    if head and head.data:
        inorder.append(head.data)
    if head and head.right:
        get_inorder(head.right)


def get_postorder(head):
    if head and head.left:
        get_postorder(head.left)
    if head and head.right:
        get_postorder(head.right)
    if head and head.data:
        postorder.append(head.data)


def get_preorder(head):
    if head and head.data:
        preorder.append(head.data)
    if head and head.left:
        get_preorder(head.left)
    if head and head.right:
        get_preorder(head.right)


# init_head = TreeNode()
# createTree(init_head)
# get_inorder(init_head)
# get_postorder(init_head)
# get_preorder(init_head)
# print('{} {}'.format('中序:', inorder))
# print('{} {}'.format('后序:', postorder))
# print('{} {}'.format('先序:', preorder))

3.测试(文件名为main_test.py):

        进行10万次测试,发现每一次对比结果,都是一致的,确认算法正确性;

from create_tree import *
from for_preorder import *
flag = True
for i in range(100000):
    init_h = TreeNode()
    createTree(init_h)
    get_inorder(init_h)
    get_postorder(init_h)
    get_preorder(init_h)
    preorder_from_in_and_post(inorder, postorder)
    if res != preorder:
        print("false!!!")
        flag = False
    res.clear()
    inorder.clear()
    postorder.clear()
    preorder.clear()
if flag:
    print("finish!!!")
    

执行结果如下:


总结

构造对数器,进行验证;理解树的递归,活用树的递归。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值