树-根据前序、中序遍历求后续遍历

该博客主要讨论如何根据给定的前序和中序遍历来求解树的后序遍历。作者首先介绍了直接构建树再进行后序遍历的方法,然后分享了一个更优的C++解决方案,该方案利用前序和中序遍历的特性,通过递归直接求解后序遍历。
摘要由CSDN通过智能技术生成
  • 题目要求
    03-树3 Tree Traversals Again (25分)
  • 分析
    我刚开始的想法是直接根据给出的操作构建相应的树,然后后序遍历即可。
  • 我的方法一代码(java版)
import java.util.*;

class Tree{
    public int left = -1;       //-1 means null
    public int right = -1;
}
public class Tree3 {
    public static Tree[] tree = new Tree[31];
    public static boolean flag = false;
    //后序遍历
    public static void postorderTraversal(int t){
        if(t == -1) return;
        if(tree[t].left != -1){
            postorderTraversal(tree[t].left);
        }
        if(tree[t].right != -1){
            postorderTraversal(tree[t].right);
        }
        if(!flag){
            System.out.print(t);
            flag = true;
        }else {
            System.out.print(" "+t);
        }

    }
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<Integer>();
        for(int i=0; i<31; i++){
            tree[i] = new Tree();
        }
        Scanner in = new Scanner(System.in);
        int N = in.nextInt();
        String line = null;
        int nowNode = -1, root = -1;
        boolean getRoot = false;
        in.nextLine();//注意这儿需要多加一个nextLine()来跳过第一行
        for(int i=1; i<=2*N; i++){
            line = in.nextLine();
            if(line.startsWith("Push")){
                if(!getRoot){//没有根的话,肯定先是构造根结点
                    nowNode = Integer.parseInt(line.split(" ")[1]);
                    root = nowNode;
                    getRoot = true;
                }else {//有根的话,push进来的必然是某个结点的子树
                    int tmp = Integer.parseInt(line.split(" ")[1]);
                    if(tree[nowNode].left == -1){
                        tree[nowNode].left = tmp;
                    }else {
                        tree[nowNode].right = tmp;
                    }
                    nowNode = tmp;
                }
                stack.push(nowNode);
            }else {
                nowNode = stack.pop();
            }
        }

        //后序遍历
        postorderTraversal(root);
        System.out.println();

    }

}

这样的代码是正确的,但是需要操作比较小心,而且这是凭自己的感觉来做的,我不太能解释清楚这样为什么是对的,虽然最后也通过了,但我感觉这不是一个完美的方法。所以我就百度了一下,发现更好的方法是这样:
其实push的顺序就是这棵树的前序遍历的顺序,pop的顺序就是中序遍历的顺序。那么这道题便转化为了已知前序、中序遍历,求后序遍历。这个函数只需要递归求解就可以了。
- 我的方法二代码 (C++版)

#include <iostream>
#include <stack>
using namespace std;

const int maxn = 31;
stack<int> s;
//保存前序、中序、后序遍历的顺序的数组
int preOrder[maxn],inOrder[maxn],postOrder[maxn];

void getPostOrder(int i,int j,int k,int n){
    if(n == 0)   return;
    //在前序遍历数组上找到根结点root
    int root = preOrder[i];
    postOrder[k+n-1] = root;//把root放在后序遍历数组上相应的位置
    //在中序遍历数组上找到根结点的位置
    int index;
    for(index=j; index<j+n; index++){
        if(inOrder[index] == root){
            break;
        }
    }
    //求左右子树的长度
    int L = index-j,R = j+n-index-1;
    //递归求解
    getPostOrder(i+1, j, k, L);//处理左子树
    getPostOrder(i+L+1, j+L+1, k+L, R);//处理右子树

}

int main(int argc, const char * argv[]) {
    int N,x;
    int index1 = 1, index2 = 1;     //preOrder[],inOrder[]的下标,从1开始
    string op;

    cin>>N;
    //根据输入得到前序、中序遍历的顺序
    for(int i=1; i<=2*N; i++){
        cin>>op;
        if(op.compare("Push") == 0){
            cin>>x;
            s.push(x);
            preOrder[index1++] = x;
        }else{
            inOrder[index2++] = s.top();
            s.pop();
        }
    }
    //求后序遍历
    getPostOrder(1, 1, 1, N);
    //输出
    cout<<postOrder[1];
    for(int i=2; i<=N; i++){
        cout<<" "<<postOrder[i];
    }
    cout<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值