根据先序遍历和后序遍历构建二叉树

关于先序遍历、中序遍历、后序遍历的定义可以参考这篇博客二叉树的遍历规则

目前能够百度到的问题大多都是根据(先序&中序)或(中序&后序)序列构建唯一二叉树,其中贴出一些提供思路的博客:二叉树的前序中序后序遍历相互求法

但是这篇博客并没有给出**(前序&后序)**的求解方法。事实上,根据前序和后序构建的二叉树不唯一,理由是前序与后序都没有明确规定节点间的父子关系,例如下图所示:
前序后序图示
下面给出已知前序&后序序列,求任一解的方法。该题同时出现于LeetCode Weekly Contest 98

LeetCode 889. Construct Binary Tree from Preorder and Postorder Traversal

Return any binary tree that matches the given preorder and postorder
traversals. Values in the traversals pre and post are distinct
positive integers.

Example 1: Input: pre = [1,2,4,5,3,6,7], post = [4,5,2,6,7,3,1]
Output: [1,2,3,4,5,6,7]

该题给出的解如下图所示:
LeetCode Demo


解题思路:
还是可以根据一般的思路,采用递归思想,对于每一个先序序列,划分出对应的根节点、左子树、右子树范围即可自上而下构建出二叉树。
例如对于上例中的先序序列[1,2,4,5,3,6,7],第一个节点一定为根节点,第2到第i个节点为左子树,第i+1到最后一个节点为右子树,那么问题就可以简化为:如何确定左右子树分界点?
思路

对于这个简化过后的问题,从后序遍历序列上很容易得到答案:
分解过程

因此,可以写出递归函数的核心代码:

#伪代码,用于理解思路
def func(pre, post):   #pre为先序序列,post为后序序列
    ...
    node = Node(pre[0])
    index = find_index(post, pre[1].val)  #查找分割点下标
    node.left = func(pre[1:index+2], post[:i+1])
    node.right = func(pre[index+2:], post[i+1:-1])
    return node

对于该题的完整解法如下所示(python):

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def constructFromPrePost(self, pre, post):
        """
        :type pre: List[int]
        :type post: List[int]
        :rtype: TreeNode
        """
        def fun(p, t):
            if len(p) == 0:
                return None
            node = TreeNode(p[0])
            if len(p) == 1:
                return node
            i = 0
            while p[1] != t[i]:
                i += 1
            node.left = fun(p[1:i+2], t[:i+1])
            node.right = fun(p[i+2:], t[i+1:-1])
            return node
        return fun(pre, post)

拓展问题:如何输出所有满足要求的二叉树?
以上。

要将二叉树先序遍历转换为后序遍历,我们不能直接通过字符串操作或简单的转换算法来实现,因为先序遍历后序遍历表示的是不同的访问顺序,这两种遍历的结果通常是不相同的。先序遍历指的是先访问根节点,然后递归地先序遍历左子树,接着递归地先序遍历右子树。后序遍历则是在先访问左子树和右子树之后再访问根节点。 如果你有一个具体的先序遍历结果,并希望得到对应的后序遍历结果,你需要提供或构建出具体的二叉树结构。如果已知二叉树先序遍历结果和一些其他信息(比如中序遍历结果或者节点的数量),可以通过递归或栈的方式重建二叉树,然后进行后序遍历。 以下是一个简单的例子,使用递归方式重建二叉树并进行后序遍历: ```c #include <stdio.h> #include <stdlib.h> // 定义二叉树节点结构体 typedef struct TreeNode { char data; struct TreeNode *left; struct TreeNode *right; } TreeNode; // 函数声明 TreeNode* buildTree(char* preorder, int* preIndex, int low, int high, int size); void postorderTraversal(TreeNode* root); void printArray(char* array, int size); int main() { char preorder[] = {'A', 'B', 'D', 'E', 'C', 'F'}; // 假设这是已知的先序遍历结果 int size = sizeof(preorder) / sizeof(preorder[0]); int preIndex = 0; TreeNode* root = buildTree(preorder, &preIndex, 0, size - 1, size); printf("Postorder Traversal: "); postorderTraversal(root); // 注意:这里没有释放分配的内存,实际使用时应适当释放内存 return 0; } // 递归构建二叉树 TreeNode* buildTree(char* preorder, int* preIndex, int low, int high, int size) { if (low > high) return NULL; TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode)); node->data = preorder[*preIndex]; *preIndex = *preIndex + 1; if (low == high) return node; int i; for (i = low; i <= high; i++) { if (preorder[i] > node->data) break; } node->left = buildTree(preorder, preIndex, *preIndex, i - 1, size); node->right = buildTree(preorder, preIndex, i, high, size); return node; } // 后序遍历二叉树 void postorderTraversal(TreeNode* root) { if (root == NULL) return; postorderTraversal(root->left); postorderTraversal(root->right); printf("%c ", root->data); } // 打印数组的函数(辅助函数,用于显示结果) void printArray(char* array, int size) { for (int i = 0; i < size; i++) { printf("%c ", array[i]); } printf("\n"); } ``` 在这个例子中,我们使用了先序遍历二叉树构建算法来重新构建原始的二叉树,然后进行后序遍历
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值