1. 程式人生 > >二叉樹幾種遍歷方式之間的轉換

二叉樹幾種遍歷方式之間的轉換

寫在前面

二叉樹的遍歷方式,基本可以歸結為四種:前序遍歷、中序遍歷、後序遍歷、層次遍歷

先序遍歷順序:根,左兒子,右兒子

中序遍歷順序:左兒子,根,右兒子

後序遍歷順序:左兒子,右兒子,根

層次遍歷順序:根據每一層的順序,由左向右依次輸出

遍歷順序及轉換

  

先序遍歷:4 1 3 2 6 5 7

中序遍歷:1 2 3 4 5 6 7

後序遍歷:2 3 1 5 7 6 4 

層次遍歷:4 1 6 3 5 7 2

變換原理:

我們知道中序遍歷和先序遍歷或者知道中序遍歷和後序遍歷就可以知道剩餘的兩種遍歷順序,因為前序遍歷在一個區間中,第一個一定是根節點,後序遍歷中最後一個一定是根節點,那麼這個區間就由中序遍歷給出

,已知根節點,在中序遍歷中找到相應位置,左邊陣列一定位於左子樹,右邊陣列一定位於右子樹中。

已知中序遍歷和後續遍歷,得到對應的二叉樹,實現:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>

using namespace std;
const int maxn = 1005;

int in_order[maxn],post_order[maxn];
int n;
int lch[maxn],rch[maxn];
queue<int> que;

int build_tree(int l1,int r1,int l2,int r2)
{
    if(l1 > r1) return 0;
    int root = post_order[r2];                 //當前區間中的根節點
    int pos = l1;
    while(in_order[pos] != root) pos++;        //在中序遍歷中找到根節點的位置,將序列分成左右兩個區間
    int cnt = pos - l1;                        //左子樹區間的長度
    printf("%d ",root);
    lch[root] = build_tree(l1,pos-1,l2,l2+cnt-1); //遍歷左子樹
    rch[root] = build_tree(pos+1,r1,l2+cnt,r2-1); //遍歷右子樹
    return root;
}
void BFS(int root)
{
    que.push(root);
    while(!que.empty())
    {
        int node = que.front();
        que.pop();
        printf("%d ",node);
        if(lch[node]) que.push(lch[node]);
        if(rch[node]) que.push(rch[node]);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i = 0;i < n;i ++)
        scanf("%d",post_order+i);                           //後序遍歷
    for(int i = 0;i < n;i ++)
        scanf("%d",in_order+i);                             //中序遍歷
    printf("先序遍歷:\n");
    int root = build_tree(0,n-1,0,n-1);
    printf("\n");


    printf("層次遍歷:\n");
    BFS(root);
    printf("\n");
}

相對應的前序和中序推後續與上面類似,只是根節點確認以及輸出順序不同

參考書籍

《演算法競賽入門經典(第二版)》劉汝佳著