根據前序、中序、后序遍歷還原二叉樹


參考:https://blog.csdn.net/changjiale110/article/details/79489884

!首先我們得知道概念:

前序遍歷:先訪問當前節點,再訪問當前節點的左子樹,最后訪問當前節點的右子樹。對於二叉樹,深度遍歷與此同。規律:根在前;子樹在根后且左子樹比右子樹靠前,且第一個就是根節點;

中序遍歷:先訪問當前節點的左子樹,然后訪問當前節點,最后是當前節點的右子樹,二叉樹,中序遍歷會得到數據升序效果。規律:根在中;左子樹在跟左邊,右子樹在根右邊,左邊部分是根結點的左子樹的中序遍歷序列,右邊部分是根結點的右子樹的中序遍歷序列 ;

后序遍歷:先訪問當前節點的左子樹,然后是當前節點的又子樹,最后是當前節點。規律:根在后;子樹在根前且左子樹比右子樹靠前,且最后一個節點是根節點。

一、前序+中序

1根據前序序列的第一個元素建立根結點;
2在中序序列中找到該元素,確定根結點的左右子樹的中序序列;
3在前序序列中確定左右子樹的前序序列;
4由左子樹的前序序列和中序序列建立左子樹;
5由右子樹的前序序列和中序序列建立右子樹。
如:已知一棵二叉樹的先序遍歷序列和中序遍歷序列分別是abdgcefh、dgbaechf,求二叉樹及后序遍歷序列。
先序:abdgcefh—>a bdg cefh
中序:dgbaechf—->dgb a echf

得出結論:a是樹根,a有左子樹和右子樹,左子樹有bdg結點,右子樹有cefh結點。
先序:bdg—>b dg

中序:dgb —>dg b

得出結論:b是左子樹的根結點,b無右子樹,有左子樹。
先序:dg—->d g

中序:dg—–>dg

得出結論:d是b左子樹的根節點,d無左子樹,g是d的右子樹

然后對於a 的右子樹類似可以推出

最后還原: a

 

后序遍歷:gdbehfca

二、后序+中序:

已知一棵二叉樹的后序序列和中序序列,構造該二叉樹的過程如下:
1. 根據后序序列的最后一個元素建立根結點;
2. 在中序序列中找到該元素,確定根結點的左右子樹的中序序列;
3. 在后序序列中確定左右子樹的后序序列;
4. 由左子樹的后序序列和中序序列建立左子樹;
5. 由右子樹的后序序列和中序序列建立右子樹

如還是上面題目:如:已知一棵二叉樹的后序遍歷序列和中序遍歷序列分別是gdbehfca、dgbaechf,求二叉樹

后序:gdbehfca—->gdb ehfc a

中序:dgbaechf—–>dgb a echf
得出結論:a是樹根,a有左子樹和右子樹,左子樹有bdg結點,右子樹有cefh結點。
后序:gdb—->gd b

中序:dgb—–>dg b

得出結論:b是a左子樹的根節點,無右子樹,有左子樹dg。

后序:gd—->g d

中序:dg—–>d g

得出結論:d是b的左子樹根節點,g是d的右子樹。

然后對於a 的右子樹類似可以推出。然后還原。
三、前序+后序

前序和后序在本質上都是將父節點與子結點進行分離,但並沒有指明左子樹和右子樹的能力,因此得到這兩個序列只能明確父子關系,而不能確定一個二叉樹。 故此法無。不能唯一確定一個二叉樹。

 代碼如下(為了方便結點用數字表示)

#include<bits/stdc++.h>
using namespace std;
int n;
int pre[100];
int in[100];
int back[100];
void get(int root,int start,int end)//求后序遍歷結果
{
    if(start>end  )
        return ;
    int i=start;
    while(i<end  && in[i]!=pre[root]) i++;
    get(root+1,start,i-1);
    get(root+1+i-start,i+1,end);
    cout << pre[root] << " ";

}
void get1(int root,int start,int end)//求前序遍歷結果
{
      if(end<start)
        return ;
      int i=end;
      while(i>start && in[i]!=back[root]) i--;
       cout << back[root] << " ";
      get1(root-1+i-end,start,i-1);
      get1(root-1,i+1,end);

}
int main()
{

    cout << "請輸入結點的個數" << endl;
    cin >> n;

    cout << "************由前序遍歷和中序遍歷求后序遍歷*****************" <<endl;;
    cout << "請輸入前序遍歷的結果" << endl;

    memset(pre,0,sizeof(pre));
    for(int i=0;i<n;i++)
    {
        cin >> pre[i];
    }
     cout << "請輸入中序遍歷的結果" << endl;

    memset(in,0,sizeof(in));
    for(int i=0;i<n;i++)
    {
        cin >> in[i];
    }
    cout << "求得后序遍歷的結果為:" <<endl;
   get(0,0,n-1);
   cout << endl;

    cout << "************由中序遍歷和后序遍歷求前序遍歷*****************" <<endl;
    memset(back,0,sizeof(back));
    memset(pre,0,sizeof(pre));
    cout << "請輸入后序遍歷的結果" << endl;
    for(int i=0;i<n;i++)
    {
        cin >> back[i];
    }
    cout << "請輸入中序遍歷的結果" << endl;
    for(int i=0;i<n;i++)
    {
        cin >> in[i];
    }
    cout << "求得前序遍歷的結果為" << endl;
    get1(n-1,0,n-1);
    return 0;
}

 


免責聲明!

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



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