PAT A1086 Tree Traversals Again [二叉树前序中序求后序]

题目描述

链接
用栈的形式给出一棵二叉树的建立的顺序,求这棵二叉树的后序遍历

分析

  • 性质:树的先序等于入栈次序,树的中序遍历等于出栈次序

    • 先序:先访问根再入栈,所以入栈次序就是先序遍历次序
    • 中序:先递归访问左子树,回溯时访问根,回溯时即出栈时,所以出栈次序就是中序遍历
  • 所以问题转换为已知先序中序,求后序
  • 已知先序中序求后序的方法
    • \(root\) 保存先序中根的位置,\(st\),\(ed\) 为中序子树的起始结束位置
    • 遍历中序,找到中序根的位置\(i\),从而分成左右子树
    • 左子树在先序中根的位置\(root+1\) ,右子树在先序中根的位置\(root+左子树结点数\)
    • 在中序中找左子树结点数\(i-st+1\) ,右子树根位置:\(root+i-st+1\)
    • 求后序:就是先左右递归dfs,再访问根
void dfs(int root, int st, int ed){
    if(st > ed) return; //中序长度小于等于0
    int i = st;
    while(i<=st&&in[i]!=pre[root]) i++;
    dfs(root+1, st, i-1);
    dfs(root+i-st+1, i+1, ed);
    ans.push_back(pre[root]);
}
  • 求层序遍历

    • 加一个变量\(index\) ,表示当前根结点在二叉树中所对应的下标(从0开始),左子树\(2*index+1\) ,右子树\(2*index+2\) (因为下标从0开始,不是从1开始)
    • 输出先序的递归的时候,把节点的\(index\)和\(value\)放进结构体里,再装进\(vector\)里
    • 在递归完成后,\(vector\)中按照\(index\)排序就是层序遍历的顺序
struct node {
    int index, value;
};
bool cmp(node a, node b) {
    return a.index < b.index;
}
vector<int> post, in;
vector<node> ans;
void dfs(int root, int st, int ed, int idx) {
    if (st > ed) return;
    int i = st;
    while (i <= end && in[i] != post[root]) i++;
    ans.push_back({idx, post[root]});
    dfs(root - 1 - ed + i, st, i - 1, 2 * idx + 1);
    dfs(root - 1, i + 1, ed, 2 * idx + 2);
}
pre(n - 1, 0, n - 1, 0);
sort(ans.begin(), ans.end(), cmp);
  • 为了避免树中多个值相同,会出问题,故先序,中序后序都保存的是\(key\) ,用\(value\) 保存实际的值

完整代码

#include<bits/stdc++.h>
using namespace std;

vector<int> pre, in, post, value;
stack<int> s;
int n,num,key;
char str[10];
//先序对应入栈,中序对应出栈
//一直先序,中序,求后序
void dfs(int root, int st, int ed){
    if(st > ed) return;
    int i = st;
    while(i<=ed && in[i] != pre[root]) i++;
    //左右根
    dfs(root+1, st, i-1);
    dfs(root+(i-st+1), i+1, ed);
    post.push_back(pre[root]);
}
int main(){
    scanf("%d",&n);
    while(~scanf("%s", str)){
        if(strlen(str) == 4){
            scanf("%d",&num);
            pre.push_back(key); //前中后序均保存key,避免值相同而出现问题
            value.push_back(num);
            s.push(key++);
        }else{
            in.push_back(s.top());
            s.pop();
        }
    }
    dfs(0, 0, n-1);
    for(int i=0;i<post.size();i++){
        if(i==0) printf("%d",value[post[i]]);
        else printf(" %d",value[post[i]]);
    }
    printf("\n");

}

原文地址:https://www.cnblogs.com/doragd/p/11284500.html

时间: 2024-10-12 22:18:16

PAT A1086 Tree Traversals Again [二叉树前序中序求后序]的相关文章

hdu 1701 (Binary Tree Traversals)(二叉树前序中序推后序)

Binary Tree Traversals Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description A binary tree is a finite set of vertices that is either empty or consists of a root r and two disjoint binary trees called

HDU 1710 二叉树遍历,输入前、中序求后序

1.HDU  1710  Binary Tree Traversals 2.链接:http://acm.hust.edu.cn/vjudge/problem/33792 3.总结:记录下根结点,再拆分左右子树,一直搜下去.感觉像dfs. 题意:二叉树,输入前.中序求后序. (1)建立出一颗二叉树,更直观.但那些指针用法并不是很懂. #include<iostream> #include<cstdio> #include<cstdlib> using namespace

UVA 536 Tree Recovery(由前序中序求后序,经典)

Tree Recovery Time Limit: 3000 MS Little Valentine liked playing with binary trees very much. Her favorite game was constructing randomly looking binary trees with capital letters in the nodes. This is an example of one of her creations: D / / B E /

关于二叉树的问题1-已知前序,中序求后序遍历

对于一棵二叉树而言,可以由其前序和中序或者中序和后序的遍历序列,确定一棵二叉树. 那么对于已知前序和中序序列,求后序序列也就是先还原二叉树,然后对其进行后序遍历即可. 二叉树结点的结构定义如下: struct TreeNode { char value; TreeNode *leftChild; TreeNode *rightChild; }; 实现代码如下: #include <stdio.h> #include <string.h> #include <stdlib.h&

已知前序中序求后序-二叉树

writer:pprp 思路很容易理解,但是实现还是有一点难度,容易错 参考书目:<算法竞赛宝典> 代码如下: //已知前序中序,求后序 #include <iostream> using namespace std; //a是前序,b是中序 void hwg(string a,string b) { int ll,lr; for(unsigned int i = 0; i < b.length(); i++) { if(a[0] == b[i]) //找到根节点 { ll

NOJ 2015年陕西省程序设计竞赛网络预赛(正式赛)(小女警的异世界之战-前序中序求后序)

A - 小女警的异世界之战 Time Limit: 1000 ms        Memory Limit: 65536 KB Submit Description 这一天,小女警花花,泡泡和毛毛来到终极Boss"Him"所在的异世界并准备与其决一死战,却被困在了他的城堡里.她们发现异世界是一个巨大的城堡.城堡由一个个大小不同的房间组成,房间有着以下的规则: 每个房间有且仅有一扇黄门,此外至多有一扇红门和一扇绿门:黄色代表通向更大的房间,绿色和红色代表通向更小的房间.很显然,如果你打开

UVa 二叉树重建(先序+中序求后序)

题意是给出先序和中序,求出后序. 先序遍历先访问根结点,通过根结点可以在中序中把序列分为左子树部分和右子树部分,我建了一个栈,因为后序遍历最后访问根结点,所以把每次访问的根结点放入栈中.因为后序遍历先是左子树然后是右子树,所以在递归的时候就先递归右子树,然后继续递归左子树. 写完程序后有个错误,找了很久才发现,就是我原本在计算左子树个数的时候,是这样计算的,pre2=mid-pre,但是当pre>mid时,就不对了.而正确计算左子树的方法应该是下面这样的. 1 #include<iostrea

HDU 1710Binary Tree Traversals(已知前序中序,求后序的二叉树遍历)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1710 解题思路:可以由先序和中序的性质得到 : 先序的第一个借点肯定是当前子树的根结点, 那么在 中序中找到这个结点, 则这个结点左边的节点属于左子树, 右边的属于右子树.然后递归遍历就可以了. 样例: 9 1 2 4 7 3 5 8 9 6 4 7 2 1 8 5 9 3 6 7 4 2 8 9 5 6 3 1 如图: 因此,用深搜就能轻松解决了,注意DFS中的变量,以及向清楚DFS的条件,这题就

POJ2255-已知二叉树前序中序求后序

水题--也可以不建立二叉树来做 如果pre[pl:pr]对应in[il:ir],那么pre[pl]是这棵树的根,它在in的位置记为root,显然root在[il,ir]内 那么二叉树的左子树是in[il:root-1],也即pre[pl+1:pl+root-il] 二叉树的右子树是in[root+1,ir],也即pre[pl+root-il+1:pr] 按照左子树-右子树-树根的后序遍历方式输出即可 附代码 #include <string> #include <iostream>