重建二叉樹


二叉樹的遍歷方式有4種:先序遍歷,中序遍歷,后序遍歷以及層次遍歷

根據中序遍歷和另外任意一種遍歷方式都可以唯一的重建二叉樹!

如果沒有中序遍歷,其余任意兩種組合均無法實現二叉樹的重建,為什么?

其實原因很簡單,先中后說的均為根結點的順序,那么左子樹一定先於右子樹遍歷到,中序遍歷可以根據根結點,將左右子樹分開!

那么如何根據中序遍歷和后序遍歷,重建出二叉樹?

思路:假設遞歸過程中,某一步的后序序列區間為[postL,postR],中序序列區間為[inL,inR];

    1. 根據后序遍歷的特點可知,postR位置為根結點;

    2. 從中序序列中,尋找出root的位置k,k左邊的均為左子樹,右邊的均為右子樹;

    3. 將左子樹區間[postL,k-1]作為新的后序和中序序列,進行遞歸。

代碼如下:

/*
 * 給定一個二叉樹的后序遍歷和中序遍歷,重建這個二叉樹
 */
/*
 * 思路:根據后序遍歷找到根結點,根據中序遍歷,根結點左邊為左子樹,根結點右邊為右子樹
 * 邊界條件:后序區間為空
 */

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;

const int maxn=50;
struct node{
    int data;
    node* lchild;
    node* rchild;
};

int pre[maxn],in[maxn],post[maxn];
int n;

node* create(int postL,int postR,int inL,int inR) //后序和中序的區間
{
    if(postL>postR)
        return NULL; 
    node* root=new node;
    root->data=post[postR];  //后序序列中,最后一個節點為根節點
    int k;
    for(k=inL;k<=inR;k++)
    {
        if(in[k]==root->data)
            break;
    }
    int numLeft=k-inL;  //左子區間為左子樹0
    root->lchild=create(postL,postL+numLeft-1,inL,k-1);
    root->rchild=create(postL+numLeft,postR-1,k+1,inR);
    return root;
}

int num=0;

void BFS(node *root){
    //層次遍歷
    queue<node*> q;
    q.push(root);
    while(!q.empty()){
        node* now=q.front();
        q.pop();
        printf("%d",now->data);
        num++;
        if(num<n)
            printf(" ");
        if(now->lchild!=NULL)
            q.push(now->lchild);
        if(now->rchild!=NULL)
            q.push(now->rchild);
    }
}
int main()
{
    scanf("%d",&n);
    int i;
    for(i=0;i<n;i++){
        scanf("%d",&post[i]);
    }

    for(i=0;i<n;i++){
        scanf("%d",&in[i]);
    }

    node* root=create(0,n-1,0,n-1);
    BFS(root);
prinf("\n");
return 0; }

僅供學習參考!

測試用例:【PAT A1020】

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM