zoukankan      html  css  js  c++  java
  • 【题集】二叉树的遍历各类题型汇总

    例1:给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。

    题目链接:https://www.patest.cn/contests/gplt/L2-006

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 100 + 10;
    int post[MAXN], in[MAXN];
    int lchild[MAXN], rchild[MAXN];
    vector<int> ans;
    int dfs(int pL, int pR, int iL, int iR, int root){
        if(pL > pR) return 0;
        int id = iL;
        while(in[id] != root) ++id;
        int cnt = id - iL;
        lchild[root] = dfs(pL, pL + cnt - 1, iL, id - 1, post[pL + cnt - 1]);
        rchild[root] = dfs(pL + cnt, pR - 1, id + 1, iR, post[pR - 1]);
        return root;
    }
    void bfs(int root){
        queue<int> q;
        q.push(root);
        while(!q.empty()){
            int x = q.front();
            ans.push_back(x);
            q.pop();
            if(lchild[x]) q.push(lchild[x]);
            if(rchild[x]) q.push(rchild[x]);
        }
    }
    int main(){
        int N;
        scanf("%d", &N);
        for(int i = 0; i < N; ++i){
            scanf("%d", &post[i]);
        }
        for(int i = 0; i < N; ++i){
            scanf("%d", &in[i]);
        }
        int root = post[N - 1];
        dfs(0, N - 1, 0, N - 1, root);
        bfs(root);
        int len = ans.size();
        for(int i = 0; i < len; ++i){
            printf("%d", ans[i]);
            if(i == len - 1) printf("
    ");
            else printf(" ");
        }
        return 0;
    }

    例2:已知前序遍历和中序遍历,求后序遍历。

    题目链接:https://www.patest.cn/contests/pat-a-practise/1138

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 50000 + 10;
    int pre[MAXN], in[MAXN];
    vector<int> ans;
    void dfs(int pL, int pR, int iL, int iR, int root){
        if(pL > pR) return;
        int id = iL;
        while(in[id] != root) ++id;
        int cnt = id - iL;
        dfs(pL + 1, pL + cnt, iL , id - 1, pre[pL + 1]);
        dfs(pL + cnt + 1, pR, id + 1, iR, pre[pL + cnt + 1]);
        ans.push_back(root);
    }
    int main(){
        int N;
        scanf("%d", &N);
        for(int i = 0; i < N; ++i){
            scanf("%d", &pre[i]);
        }
        for(int i = 0; i < N; ++i){
            scanf("%d", &in[i]);
        }
        int root = pre[0];
        dfs(0, N - 1, 0, N - 1, root);
        printf("%d
    ", ans[0]);
        return 0;
    }

    另一种做法:

    因为输出的是后序遍历(左右中)第一个元素,因此对于某元素,

    如果有左子树的话,就不用研究右子树了;

    如果没有左子树,就研究右子树;

    如果左右子树都没有,就研究他本身。(遇到的第一个叶子结点就是答案)

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 50000 + 10;
    int pre[MAXN], in[MAXN];
    map<int, int> mp;
    void dfs(int pL, int pR, int iL, int iR, int root){
        if(pL > pR) return;
        int id = mp[root];
        int cnt = id - iL;
        if(iL != id){
            dfs(pL + 1, pL + cnt, iL, id - 1, pre[pL + 1]);
        }
        else if(iR != id){
            dfs(pL + cnt + 1, pR, id + 1, iR, pre[pL + cnt + 1]);
        }
        else{
            printf("%d
    ", root);
            return;
        }
    }
    int main(){
        int N;
        scanf("%d", &N);
        for(int i = 0; i < N; ++i){
            scanf("%d", &pre[i]);
        }
        for(int i = 0; i < N; ++i){
            scanf("%d", &in[i]);
            mp[in[i]] = i;
        }
        int root = pre[0];
        dfs(0, N - 1, 0, N - 1, root);
        return 0;
    } 

     例3:已知前序遍历和后序遍历,求中序遍历。

    思路:前序遍历的第一个元素是根。

    若只有左子树,则前序遍历的第二个元素和后序遍历的倒数第二个元素相同,且都是左子树的根;

    若只有右子树,则前序遍历的第二个元素和后序遍历的倒数第二个元素相同,且都是右子树的根;

    若既有左子树又有右子树,则前序遍历的第二个元素是左子树的根,后序遍历的倒数第二个元素是右子树的根;

    即,若前序遍历的第二个元素和后序遍历的倒数第二个元素相同,则对于当前根结点来说有两种可能,要么只有左子树,要么只有右子树。这两种情况下,前序遍历是相同的,后序遍历也是相同的,但中序遍历不同。

    (1)求任意一种中序遍历。

    题目链接:https://www.patest.cn/contests/pat-a-practise/1119

    #include<cstdio>
    #include<vector>
    #include<map>
    using namespace std;
    const int MAXN = 30 + 10;
    int pre[MAXN], pos[MAXN];
    int cnt;
    map<int, int> mp1;
    map<int, int> mp2;
    vector<int> ans;
    void dfs(int prL, int prR, int poL, int poR, int root){
        if(prL > prR) return;
        if(prL == prR){
            ans.push_back(root);
            return;
        }
        int tmp1 = pre[prL + 1];
        int tmp2 = pos[poR - 1];
        if(tmp1 != tmp2){
            dfs(mp1[tmp1], mp1[tmp2] - 1, poL, mp2[tmp1], pre[mp1[tmp1]]);
            ans.push_back(root);
            dfs(mp1[tmp2], prR, mp2[tmp1] + 1, poR - 1, pre[mp1[tmp2]]);
        }
        else{
            ++cnt;
            dfs(mp1[tmp1], prR, poL, mp2[tmp1], pre[mp1[tmp1]]);
            ans.push_back(root);
        }
    }
    int main(){
        int N;
        scanf("%d", &N);
        for(int i = 0; i < N; ++i){
            scanf("%d", &pre[i]);
            mp1[pre[i]] = i;
        }
        for(int i = 0; i < N; ++i){
            scanf("%d", &pos[i]);
            mp2[pos[i]] = i;
        }
        int root = pre[0];
        dfs(0, N - 1, 0, N - 1, root);
        if(cnt >= 1) printf("No
    ");
        else printf("Yes
    ");
        int len = ans.size();
        for(int i = 0; i < len; ++i){
            printf("%d", ans[i]);
            if(i == len - 1) printf("
    ");
            else printf(" ");
        }
        return 0;
    }
    

     (2)求中序遍历可能的种数。

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1832

    思路:运算结果涉及高精度计算。

    #include<cstdio>
    #include<vector>
    #include<map>
    using namespace std;
    const int MAXN = 10000 + 10;
    const int MOD = 1000000000;
    int pre[MAXN], pos[MAXN];
    int cnt;
    map<int, int> mp1;
    map<int, int> mp2;
    int ans[MAXN];
    void dfs(int prL, int prR, int poL, int poR){
        if(prL >= prR) return;
        int tmp1 = pre[prL + 1];
        int tmp2 = pos[poR - 1];
        if(tmp1 != tmp2){
            dfs(mp1[tmp1], mp1[tmp2] - 1, poL, mp2[tmp1]);
            dfs(mp1[tmp2], prR, mp2[tmp1] + 1, poR - 1);
        }
        else{
            ++cnt;
            dfs(prL + 1, prR, poL, poR - 1);
        }
    }
    void solve(int n, int k){//将最终的结果每隔9位数存在ans数组中
        int len = 1;
        ans[1] = 1;
        while(k--){
            for(int i = 1; i <= len; ++i){
                ans[i] *= n;
            }
            for(int i = 1; i <= len; ++i){
                ans[i + 1] += ans[i] / MOD;
                ans[i] %= MOD;
            }
            if(ans[len + 1]) ++len;
        }
        for(int i = len; i >= 1; --i){
            if(i == len) printf("%d", ans[i]);
            else printf("%09d", ans[i]);
        }
        printf("
    ");
    }
    int main(){
        int N;
        scanf("%d", &N);
        for(int i = 0; i < N; ++i){
            scanf("%d", &pre[i]);
            mp1[pre[i]] = i;
        }
        for(int i = 0; i < N; ++i){
            scanf("%d", &pos[i]);
            mp2[pos[i]] = i;
        }
        dfs(0, N - 1, 0, N - 1);
        solve(2, cnt);//计算2的cnt次方,不取模
        return 0;
    }
    
  • 相关阅读:
    软工网络15团队作业4——Alpha阶段敏捷冲刺
    (转) linux目录结构详细介绍
    ActiveMQ使用记录
    .NET4.5中WCF中默认生成的basicHttpsBinding的研究
    StackExchange.Redis的使用
    微信/QQ机器人的实现
    EntityFramework中的datetime2异常的解决
    在Web API中使用Swagger-UI开源组件(一个深坑的解决)
    (转)使用Migrations更新数据库结构(Code First )
    WebApi中帮助页Description的中文显示
  • 原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/8452359.html
Copyright © 2011-2022 走看看