首页 > 其他分享 >PAT甲级-1086 Tree Traversals Again

PAT甲级-1086 Tree Traversals Again

时间:2024-09-21 22:22:10浏览次数:3  
标签:1086 遍历 PAT Again bl 中序 int 先序 root

题目

 

题目大意

题目给出二叉树的节点个数,并给出用栈遍历树的过程。要求输出树的后序遍历,不能有多余空格。

思路

可以看出,栈遍历输出的是树的中序遍历,而依次push进栈的是先序遍历的顺序。题目要求后序,即已知先序和中序遍历,求后序遍历。

可以先依次遍历先序,例如从先序第一个值开始,然后遍历中序找到与先序第一个值相等的值,中序中的这个值是树的根,左边的各值是它的左子树,右边是它的右子树。接着轮到先序第二个值,在中序的左子树中找到和第二个值相等的值,这个值是左子树中的一个根节点,左边是它的左子树,右边是它的右子树,就有些递归的感觉了。

由中序的树到左子树再到左子树的左子树,树的范围在缩小,当缩小到仅剩一个值的时候,就可以将它插入到树中了。中序树的范围可以由两个指针ml,mr表示。

前面说先序依次遍历,但在中序树的范围缩小后,先序的遍历范围也在缩小,即要满足先序的遍历范围恰好覆盖中序树的所有节点,否则就会重复遍历。先序数的范围可以用两个指针bl,br表示。

这也就确定了递归函数中的参数,分别是根节点、ml、mr、bl、br。

知识点

C++中对象和指针的声明是不一样的。声明对象时会直接为其分配空间,而声明指针不会,需要用new来手动显式分配空间。

指针在使用前最好被初始化为nullptr。

代码

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

struct node{
    int data;
    node *lchild, *rchild;
};

vector<int> bef;  // 前序遍历
vector<int> mid;  // 中序遍历
vector<int> aft;  // 后序遍历

void buildTree(node * &root, int bl, int br, int ml, int mr){
    if (bl > br || ml > mr){
        return;
    }else{
        int pos;
        for (int i = ml; i <= mr; i++){
            if (bef[bl] == mid[i]){
                pos = i;
                break;
            }
        }  // 找到根节点
        root = new node();  // 添加根节点,指针都要被显式的分配内存,对象是隐式分配的
        root->data = bef[bl];
        root->lchild = root->rchild = nullptr;
        buildTree(root->lchild, bl + 1, bl + (pos - ml), ml, pos - 1);  // 确定先序节点的遍历范围是从bl + 1到bl + pos - bl
        buildTree(root->rchild, bl + (pos - ml) + 1, br, pos + 1, mr);  // 从bl + pos - bl + 1到br
    }
}  // 由先序和中序构造二叉树

void traverseAfter(node * root){
    if (root == nullptr){
        return;
    }
    traverseAfter(root->lchild);
    traverseAfter(root->rchild);
    aft.push_back(root->data);
}  // 后序遍历

int main(){
    int n;
    cin >> n;
    stack<int> s;
    for (int i = 0; i < 2 * n; i++){
        string a;
        cin >> a;
        if (a[1] == 'u'){
            int num;
            cin >> num;
            bef.push_back(num);
            s.push(num);
        }else{
            mid.push_back(s.top());
            s.pop();
        }
    }

    node * root = nullptr;  // 声明二叉树的根节点并初始化
    buildTree(root, 0, n - 1, 0, n - 1);
    traverseAfter(root);
    for (int i = 0; i < n; i++){
        cout << aft[i];
        if (i != n - 1){
            cout << " ";
        }
    }
    cout << endl;

    return 0;
}

标签:1086,遍历,PAT,Again,bl,中序,int,先序,root
From: https://blog.csdn.net/weixin_74092648/article/details/142425775

相关文章