先序中序轉二叉樹

先序中序

在紙上計算一下他們轉的過程就很容易發現規律
寫程序更簡單,只需要計算出每個子樹的起始位置
計算的時候使用靜態鏈表更爲方便
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
using namespace std;
struct node
{
    int Data;
    int Right, Left;
};
vector<int> in, pre;
vector<node> T;
map<int, int> mp;
// 靜態指針
int p = -1;
// 由先序、中序建立
int Build(int inL, int inR, int preL, int preR)
{
    // 防止越界
    if (inL > inR || preL > preR)
        return -1;
    // 先序的第一個結點是當前二叉樹的結點
    int data = pre[preL];
    // 取出在中序中的位置
    int index = mp[data];
    // 相當於指針 因爲p在後面會發生變化 所以先記錄
    int pos = ++p;
    // 算出當前結點的左子樹的長度 方便下面的計算
    int l = index - inL;
    T[pos].Data = data;
    // 下面的公式是在紙上推導出來的,規律很容易發現
    // 在紙上寫出先序和中序 發現規律
    // 分別pos的兩個子樹的起始位子
    T[pos].Left = Build(inL, index - 1, preL + 1, preL + l);
    T[pos].Right = Build(index + 1, inR, preL + l + 1, preR);
    // 最後返回pos下標
    return pos;
}
// 後序
void dfs(int k)
{
    if (T[k].Left != -1)
    {
        dfs(T[k].Left);
    }
    if (T[k].Right != -1)
    {
        dfs(T[k].Right);
    }
    cout << T[k].Data<<' ';
}
// 層次
void bfs()
{
    queue<int> q;
    q.push(0);
    while (!q.empty())
    {
        int x = q.front();
        cout << x << " ";
        q.pop();
        if (T[x].Left != -1)
            q.push(T[x].Left);
        if (T[x].Right != -1)
            q.push(T[x].Right);
    }
}
int main()
{
    int N;
    cin >> N;
    T.resize(N);
    int x;
    for (int i = 0; i < N; i++)
    {
        cin >> x;
        mp[x] = i;
        in.push_back(x);
    }
    for (int i = 0; i < N; i++)
    {
        cin >> x;
        pre.push_back(x);
    }
    Build(0, N - 1, 0, N - 1);
    // bfs();
    // dfs(0);
    return 0;
}

後序中序

#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
using namespace std;
struct node
{
    int Data;
    int Right, Left;
};
vector<int> in, post;
vector<node> T;
map<int, int> mp;
// 靜態指針
int p = -1;
// 由先序、中序建立
int Build(int inL, int inR, int postL, int postR)
{
    // 防止越界
    if (inL > inR || postL > postR)
        return -1;
    // 後序的最後一個結點是當前二叉樹的結點
    int data = post[postR];
    // 取出在中序中的位置
    int index = mp[data];
    // 相當於指針 因爲p在後面會發生變化 所以先記錄
    int pos = ++p;
    // 算出當前結點的左子樹的長度 方便下面的計算
    int l = index - inL;
    T[pos].Data = data;
    // 下面的公式是在紙上推導出來的,規律很容易發現
    // 在紙上寫出後序和中序 發現規律
    // 分別pos的兩個子樹的起始位置
    T[pos].Left = Build(inL, index - 1, postL, postL + l - 1);
    T[pos].Right = Build(index + 1, inR, postL + l, postR - 1);
    // 最後返回pos下標
    return pos;
}
// 先序
void dfs(int k)
{
    cout << T[k].Data << ' ';
    if (T[k].Left != -1)
    {
        dfs(T[k].Left);
    }
    if (T[k].Right != -1)
    {
        dfs(T[k].Right);
    }
}
// 層次
void bfs()
{
    queue<int> q;
    q.push(0);
    while (!q.empty())
    {
        int x = q.front();
        cout << x << " ";
        q.pop();
        if (T[x].Left != -1)
            q.push(T[x].Left);
        if (T[x].Right != -1)
            q.push(T[x].Right);
    }
}
int main()
{
    int N;
    cin >> N;
    T.resize(N);
    int x;
    for (int i = 0; i < N; i++)
    {
        cin >> x;
        mp[x] = i;
        in.push_back(x);
    }
    for (int i = 0; i < N; i++)
    {
        cin >> x;
        post.push_back(x);
    }
    Build(0, N - 1, 0, N - 1);
    // bfs();
    dfs(0);
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章