算法基础 - 通过前序遍历和中序遍历得到后续遍历

思想

思想很简单,前序遍历,第一个节点一定是当前树的根节点,而这个节点在中序遍历中,分割了左右子树。

假如前序:

root left1 left2 left3 right1 right2

中序一定是:

left left left root right right

虽然left在中序的顺序不能直接通过前序得到,但是一定知道的是,在中序遍历中,root分割了左右子树。然后递归得到左右子树的遍历,就可以得到整个树了。

代码如下:

#include <iostream>
#include <cstring>
#include <string>

using namespace std;

string res;

void postOrder(string preorder, string midorder, int sp, int se, int ms, int me){
    if(sp > se || ms > me) return;
    res = preorder[sp] + res;
    int mid = ms;
    for(mid = ms; mid <= me; mid++){
        if(midorder[mid] == preorder[sp]) break;
    }
    postOrder(preorder, midorder, mid-ms+sp+1, se, mid+1, me);//这里是先右孩子
    postOrder(preorder, midorder, sp+1, mid-ms+sp, ms, mid-1); //然后左孩子
}

int main(){
    string str1, str2;
    while(cin>>str1>>str2){
        postOrder(str1, str2, 0, (int)str1.length()-1, 0, (int)str2.length()-1);
        cout<<res<<endl;
        res = "";
    }
    return 0;
}

上面是返回后续遍历的序列的,假如想重构这棵树,思想就是:

consTree(preSe, midSe, ps, pe, ms, me){
    node = new node(preSe[ps]); //构造当前节点
    node->left = consTree(preSe,midSe, ps+1, mid-ms+ps, ms, mid-1);//节点做孩子等于左子树的根节点
    node->right = consTree(mid-ms+ps+1, pe, mid+1, me);//同理
    return node;
}

完整代码如下:

struct TreeNode{
    int val;
    TreeNode * left, *right;
    TreeNode(int x): val(x), left(NULL), right(NULL){}
};

TreeNode* constTree(string preorder, string midorder, int sp, int se, int ms, int me){
    if (sp > se || ms > me) {
        return NULL;
    }
    TreeNode * node = new TreeNode(preorder[sp]);
    int mid = ms;
    for(mid = ms; mid <= me; mid++){
        if(midorder[mid] == preorder[sp]) break;
    }
    node->left = constTree(preorder, midorder, sp+1, mid-ms+sp, ms, mid-1);
    node->right = constTree(preorder, midorder, mid-ms+sp+1, se, mid+1, me);
    return node;
}

同理其实可以得到通过后续遍历和中序遍历得到前序遍历的。

但是不能通过前序遍历和后续遍历得到中序遍历,会有歧义的。

时间: 2024-10-13 12:26:33

算法基础 - 通过前序遍历和中序遍历得到后续遍历的相关文章

C++用非递归实现二叉树的前序排列,中序排列,后续排列

前序排列的非递归实现: Template<class T> Void PreOrder(BinaryTreeNode<T> *t) { stack <BinaryTreeNode<T> *> S(Maxlength); BinaryTreeNode<T> *p=t; do{ while(p){ visit(p);//访问P S.Add(p); p=p->LeftChild; } If(!S.IsEmpty()){ S.Delete(p);

已知二叉树的前序遍历、中序遍历或者中序遍历、后序遍历求二叉树结构的算法

二叉树中的前序遍历是先访问根结点,再访问左子树,右子树. 中序遍历是先访问左子树,再是根结点,最后是右子树. 后序遍历是先访问左子树,再是右子树,最后是根结点. 算法思路是先根据前序遍历的第一个结点或者后序遍历的最后一个结点,查找对应在中序遍历中的位置,就可以确定左子树包含的元素和右子树包含的元素,最后通过递归来实现就可以了. 二叉树的表示形式为 //二叉树的结构表示为 class TreeNode { int val; TreeNode left; TreeNode right; TreeNo

二叉查找树的前序遍历,后序遍历和中序遍历互求算法模板

面试的痛 前几天去阿里面试,一时忘记了二叉树的前序遍历中序遍历和后序遍历的概念,已经想死了. 然后最近去腾讯面试,被问到怎么已知前序遍历/后序遍历 + 中序遍历,求后序遍历/前序遍历,看来这种问题很喜欢考. 其实这个问题想清楚了很简单,只要把这三个概念理解透彻就可以做出来了,比如前序遍历的第一个值一定是根节点,然后这个根节点对应到中序遍历里面,在中序遍历的这个值的两边的值,一定在以此节点为根节点的两个子树上,同理,后序遍历也一样. 已知前序遍历和后序遍历是不能求唯一的中序遍历树的. #inclu

二叉树——前序遍历、中序遍历、后序遍历、层序遍历详解(递归非递归)

前言 前面介绍了二叉排序树的构造和基本方法的实现.但是排序遍历也是比较重要的一环.所以笔者将前中后序.和层序遍历梳理一遍. 了解树的遍历,需要具有的只是储备有队列,递归,和栈.这里笔者都有进行过详细介绍,可以关注笔者数据结构与算法专栏.持续分享,共同学习. 层序遍历 层序遍历.听名字也知道是按层遍历.我们知道一个节点有左右节点.而每一层一层的遍历都和左右节点有着很大的关系.也就是我们选用的数据结构不能一股脑的往一个方向钻,而左右应该均衡考虑.这样我们就选用队列来实现. 对于队列,现进先出.从根节

算法学习 - 表达树的建立(后缀表达式法),树的先序遍历,中序遍历,后序遍历

表达树就是根据后缀表达式来建立一个二叉树. 这个二叉树的每个叶子节点就是数,真祖先都是操作符. 通过栈来建立的,所以这里也会有很多栈的操作. 树的先序遍历,中序遍历,后序遍历的概念我就不讲了,不会的自行百度,不然也看不懂我的代码. 下面是代码: // // main.cpp // expressionTree // // Created by Alps on 14-7-29. // Copyright (c) 2014年 chen. All rights reserved. // #includ

根据二叉树的前序遍历和中序遍历重建二叉树

题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回. 1 /** 2 * Definition for binary tree 3 * struct TreeNode { 4 * int val; 5 * TreeNode *left; 6 * TreeNode *right; 7 * TreeNode(

根据前序遍历和中序遍历求后序遍历

根据前序遍历和中序遍历求后序遍历 一道HULU的笔试题(How I wish yesterday once more) 假设有棵树,长下面这个样子,它的前序遍历,中序遍历,后续遍历都很容易知道. PreOrder:         GDAFEMHZ InOrder:            ADEFGHMZ PostOrder:       AEFDHZMG 现在,假设仅仅知道前序和中序遍历,如何求后序遍历呢?比如,已知一棵树的前序遍历是"GDAFEMHZ",而中序遍历是"AD

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

问题描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回. 思路: 在二叉树的前序遍历序列中,第一个数字总是树的根结点的值.但在中序遍历序列中,根结点的值在序列的中间,左子树的结点的值位于根结点的值的左边,而右子树的结点的值位于根结点的值的右边.因此我们需要扫描中序遍历序列,才能找到根结点的值. 如下图所示,

前序遍历和中序遍历重建二叉树

对于二叉树,在此我不做过多讲解,如有不懂,请参照一下链接点击打开链接 1.在此二叉树的定义: struct BinaryTreeNode     {         BinaryTreeNode<T> *_Left;         BinaryTreeNode<T> *_Right;         T _data;     public:         BinaryTreeNode(const T& x)             :_Left(NULL)