PAT-A 1127题解

PAT-A 1127题解

题目链接:
https://pintia.cn/problem-sets/994805342720868352/problems/994805349394006016

题意分析

给定后序遍历和中序遍历的序列,要求非正常层序遍历的输出(先左后右边,再右边往左边,接着从左往右…………以此类推)

算法分析

这道题要解决两个问题:

  1. 怎么把这个二叉树构建出来
  2. 怎么交替的按照从右往左和从左往右层序遍历。
    首先这个构建二叉树的算法和平时我们用到的差不了太多。代码如下:
node* create_tree(int inL,int inR,int postR){//postR表示的是postorder的根节点的下标
    if(inL > inR) {
        return NULL;
    }
    node* root = new node;
    root->val = post[postR];//没有欲望
    int in_root_pos = pos_map[post[postR]];
    int right_num = inR-in_root_pos;
    root->lc = create_tree(inL,in_root_pos-1,postR-right_num-1);
    root->rc = create_tree(in_root_pos+1,inR,postR-1);
    return root;
}

当然要注意,无论是先序还是后续也好,都要以根节点为研究对象,看一个方向。比如先序遍历,只要找到了根节点,那么它的子树的结点就一定在它的右边,而后续遍历则相反,一定在它的左边。这一点要注意。

对于问题二,既然要交替输出左右、右左这样的顺序,我们想到了栈这个FILO数据结构。假设我们构造两个栈,先把结点放进去,然后把他的子结点都放到另一个栈里面。再从另一个栈里不断地把里面的元素出栈,出栈后把他们的左右儿子放到另一个栈里面,如此循环往复,直到所有元素都被清空。

完整代码


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

const int MAX_N = 32;
int post[MAX_N],in[MAX_N];
unordered_map<int,int> pos_map;
int n;
int count = 0;
struct node
{
    node* lc,*rc;
    int val;
};

node* create_tree(int inL,int inR,int postR){//postR表示的是postorder的根节点的下标
    if(inL > inR) {
        return NULL;
    }
    node* root = new node;
    root->val = post[postR];//没有欲望
    int in_root_pos = pos_map[post[postR]];
    int right_num = inR-in_root_pos;
    root->lc = create_tree(inL,in_root_pos-1,postR-right_num-1);
    root->rc = create_tree(in_root_pos+1,inR,postR-1);
    return root;
}
void print(node *root){
    stack<node*> s_left,s_right;
    int cnt = 0;
    s_left.push(root);
    while (s_left.size() > 0 || s_right.size() > 0)
    {
        if(cnt%2==0){
            while (s_left.size())
            {
                node* now = s_left.top();
                cout<<now->val;
                count++;
                if(count == n){
                    cout<<endl;
                }
                else cout<<" ";
                if(now->rc!=NULL){
                    s_right.push(now->rc);
                }
                if(now->lc!=NULL){
                    s_right.push(now->lc);
                }
                s_left.pop();
            }
        }
        else
        {
            while (s_right.size())
            {
                node* now = s_right.top();
                cout<<now->val;
                count++;
                if(count == n){
                    cout<<endl;
                }
                else cout<<" ";
                if(now->lc != NULL){
                    s_left.push(now->lc);
                }
                if(now->rc != NULL){
                    s_left.push(now->rc);
                }
                s_right.pop();
            }
        }
        cnt++;
    }
}

void postOrder(node* root){
    if(root == NULL){
        return;
    }
    postOrder(root->lc);
    postOrder(root->rc);
    cout<<root->val<<" ";
}
int main(){
    cin>>n;
    for(int i = 1;i<= n;i++){
        cin>>in[i];
        pos_map[in[i]] = i;
    }
    for(int i  =1;i<= n;i++){
        cin>>post[i];
    }
    node* root = create_tree(1,n,n);
    //postOrder(root1);
    print(root);
    system("pause");
    return 0;
}       
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值