【二叉树】由前序、中序遍历推后序遍历,由中序、后序遍历推前序遍历方法

学习资料
1.推断二叉树
2.AcWing 3598. 二叉树遍历(暑假每日一题2022)


1.函数对比

前序中序推后序
image

void dfs(string mid, string pre)
{
    if (mid.size())
    {
        char root = pre[0];
        int cur = mid.find(root);
        dfs(mid.substr(0, cur), pre.substr(1, cur));
        dfs(mid.substr(cur + 1), pre.substr(cur + 1));
        cout << root;
    }
}

中序后序推前序
image

注意:s.substr(a, len)表示取字符串s的下标a开始,长度为len的字符串
其中,第一个参数a表示起始下标,第二参数len表示长度。

void dfs(string mid, string last)
{
    if (mid.size())
    {
        char root = last[last.size() - 1];
        int cur = mid.find(root);
        cout << root;
        dfs(mid.substr(0, cur), last.substr(0, cur));
        dfs(mid.substr(cur + 1), last.substr(cur, last.size() - cur - 1));
    }
}

前序中序建树

char build(int il, int ir, int pl, int pr)
{
    char root = pre[pl];
    int k = pos[root];
    if (il < k) l[root] = build(il, k - 1, pl + 1, pl + 1 + k - 1 - il);
    if (ir > k) r[root] = build(k + 1, ir, pl + 1 + k - 1 - il + 1, pr);
    return root;
}

中序后序建树

char build(int il, int ir, int pl, int pr)
{
    char root = last[pr];
    int k = pos[root];
    if (il < k) l[root] = build(il, k - 1, pl, k - 1 - il + pl);
    if (ir > k) r[root] = build(k + 1, ir, k - 1 - il + pl + 1, pr - 1);
    return root;
}

2.由前序、中序推后序遍历

P1827 [USACO3.4] 美国血统 American Heritage

不建树写法

#include <iostream>

using namespace std;

void dfs(string mid, string pre)
{
    if (mid.size())
    {
        char root = pre[0];
        int cur = mid.find(root);
        dfs(mid.substr(0, cur), pre.substr(1, cur));
        dfs(mid.substr(cur + 1), pre.substr(cur + 1));
        cout << root;
    }
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    string mid, pre;
    cin >> mid >> pre;
    dfs(mid, pre);
    return 0;
}

建树写法

#include <iostream>
#include <unordered_map>

using namespace std;

int n;
string mid, pre;
unordered_map<char, int> l, r, pos;

char build(int il, int ir, int pl, int pr)
{
    char root = pre[pl];
    int k = pos[root];
    if (il < k) l[root] = build(il, k - 1, pl + 1, pl + 1 + k - 1 - il);
    if (ir > k) r[root] = build(k + 1, ir, pl + 1 + k - 1 - il + 1, pr);
    return root;
}

void dfs(char root)
{
    if (l.count(root)) dfs(l[root]);
    if (r.count(root)) dfs(r[root]);
    cout << root;
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> mid >> pre;
    n = mid.size();
    for (int i = 0; i < n; i++) pos[mid[i]] = i;
    char root = build(0, n - 1, 0, n - 1);
    dfs(root);
    return 0;
}

3598. 二叉树遍历

不建树写法

#include <iostream>

using namespace std;

void dfs(string mid, string pre)
{
    if (mid.size())
    {
        char root = pre[0];
        int cur = mid.find(root);
        dfs(mid.substr(0, cur), pre.substr(1, cur));
        dfs(mid.substr(cur + 1), pre.substr(cur + 1));
        cout << root;
    }
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    string mid, pre;
    while (cin >> pre >> mid)
    {
        dfs(mid, pre);
        cout << '\n';
    }
    return 0;
}

建树写法

#include <iostream>
#include <unordered_map>

using namespace std;

int n;
string mid, pre;
unordered_map<char, int> l, r, pos;

char build(int il, int ir, int pl, int pr)
{
    char root = pre[pl];
    int k = pos[root];
    if (il < k) l[root] = build(il, k - 1, pl + 1, pl + 1 + k - 1 - il);
    if (ir > k) r[root] = build(k + 1, ir, pl + 1 + k - 1 - il + 1, pr);
    return root;
}

void dfs(char root)
{
    if (l.count(root)) dfs(l[root]);
    if (r.count(root)) dfs(r[root]);
    cout << root;
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    while (cin >> pre >> mid)
    {
        n = mid.size();
        pos.clear(), l.clear(), r.clear();
        for (int i = 0; i < n; i++) pos[mid[i]] = i;
        char root = build(0, n - 1, 0, n - 1);
        dfs(root);
        cout << '\n';
    }
    return 0;
}

1631. 后序遍历

建树写法

#include <iostream>
#include <unordered_map>

using namespace std;

const int N = 50010;

int n;
unordered_map<int, int> l, r, pos;
int pre[N], in[N], post[N], cnt;

int build(int il, int ir, int pl, int pr)
{
    int root = pre[pl];
    int k = pos[root];
    if (il < k) l[root] = build(il, k - 1, pl + 1, pl + 1 + k - 1 - il);
    if (ir > k) r[root] = build(k + 1, ir, pl + 1 + k - 1 - il + 1, pr);
    return root;
}

void dfs(int root)
{
    if (l.count(root)) dfs(l[root]);
    if (r.count(root)) dfs(r[root]);
    post[cnt++] = root;
}

int main()
{
    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]);
        pos[in[i]] = i;
    }
    int root = build(0, n - 1, 0, n - 1);
    dfs(root);
    printf("%d\n", post[0]);
    return 0;
}

3.由中序、后序推前序遍历

P1030 [NOIP 2001 普及组] 求先序排列

不建树写法

#include <iostream>

using namespace std;

void dfs(string mid, string last)
{
    if (mid.size())
    {
        char root = last[last.size() - 1];
        int cur = mid.find(root);
        cout << root;
        dfs(mid.substr(0, cur), last.substr(0, cur));
        dfs(mid.substr(cur + 1), last.substr(cur, last.size() - cur - 1));
    }
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    string mid, last;
    cin >> mid >> last;
    dfs(mid, last);
    return 0;
}

建树写法

#include <iostream>
#include <unordered_map>

using namespace std;

string mid, last;
unordered_map<char, int> l, r, pos;

char build(int il, int ir, int pl, int pr)
{
    char root = last[pr];
    int k = pos[root];
    if (il < k) l[root] = build(il, k - 1, pl, k - 1 - il + pl);
    if (ir > k) r[root] = build(k + 1, ir, k - 1 - il + pl + 1, pr - 1);
    return root;
}

void dfs(char root)
{
    cout << root;
    if (l.count(root)) dfs(l[root]);
    if (r.count(root)) dfs(r[root]);
}

int main()
{
    cin >> mid >> last;
    int n = mid.size();
    for (int i = 0; i < n; i++) pos[mid[i]] = i;
    char root = build(0, n - 1, 0, n - 1);
    dfs(root);
    return 0;
}

4.由前序、中序构建二叉树

105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int n;
    unordered_map<int, int> pos;

    TreeNode* build(vector<int> &preorder, vector<int> &inorder, int il, int ir, int pl, int pr)
    {
        TreeNode* root = new TreeNode(preorder[pl]);
        int k = pos[root->val];
        if (il < k) //如果左子树存在,递归构建左子树
            root->left = build(preorder, inorder, il, k - 1, pl + 1, pl + 1 + k - 1 - il);
        if (ir > k) //如果右子树存在,递归构建右子树
            root->right = build(preorder, inorder, k + 1, ir, pl + 1 + k - 1 - il + 1, pr);
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        n = preorder.size();
        for (int i = 0; i < n; i++) pos[inorder[i]] = i;
        return build(preorder, inorder, 0, n - 1, 0, n - 1);
    }
};

5.由中序、后序构建二叉树

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int n;
    unordered_map<int, int> pos;

    TreeNode* build(vector<int> &inorder, vector<int> &postorder, int il, int ir, int pl, int pr)
    {
        TreeNode* root = new TreeNode(postorder[pr]);
        int k = pos[root->val];
        if (il < k) 
            root->left = build(inorder, postorder, il, k - 1, pl, pl + k - 1 - il);
        if (ir > k) 
            root->right = build(inorder, postorder, k + 1, ir, pl + k - 1 - il + 1, pr - 1);
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        n = inorder.size();
        for (int i = 0; i < n; i++) pos[inorder[i]] = i;
        return build(inorder, postorder, 0, n - 1, 0, n - 1);
    }
};

由中序后序推层序 1497. 树的遍历

先建树,再BFS求层序遍历序列

#include <iostream>
#include <queue>
#include <unordered_map>

using namespace std;

const int N = 40;

int n;
int mid[N], last[N];
unordered_map<int, int> l, r, pos;

int build(int il, int ir, int pl, int pr)
{
    int root = last[pr]; // 后序遍历的最后一个结点是根结点
    int k = pos[root];   // k是根结点在中序遍历中的下标
    if (il < k)          // 如果左子树存在
        l[root] = build(il, k - 1, pl, pl + k - 1 - il);
    if (k < ir) // 如果右子树存在
        r[root] = build(k + 1, ir, pl + k - 1 - il + 1, pr - 1);
    return root;
}

void bfs(int root)
{
    queue<int> q;
    q.push(root);

    while (q.size())
    {
        int t = q.front();
        q.pop();

        cout << t << ' ';
        if (l.count(t)) q.push(l[t]);
        if (r.count(t)) q.push(r[t]);
    }
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n;
    for (int i = 0; i < n; i++) cin >> last[i];
    for (int i = 0; i < n; i++)
    {
        cin >> mid[i];
        pos[mid[i]] = i;
    }
    int root = build(0, n - 1, 0, n - 1);
    bfs(root);
    return 0;
}
posted @   Tshaxz  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
Language: HTML
点击右上角即可分享
微信分享提示