樹遍歷的應用——樹的重建

目錄

需要用到的概念

題目描述

解題思路

代碼實現


  • 需要用到的概念

    • 有根二叉樹:如果一根樹擁有一個根結點,且所有結點的子結點數都不超過2,那麼這棵樹稱爲有根二叉樹。
    • 樹的遍歷:
      • 前序遍歷(Preorder Tree Walk) :按照根結點、左子樹、右子樹的順序輸出結點編號。
      • 中序遍歷(Inorder Tree Walk):按照左子樹、根結點、右子樹的順序輸出結點編號。
      • 後序遍歷(PostOrder Tree Walk):按照左子樹、右子樹、根結點的順序輸出結點編號。
      • (可以發現左子樹、右子樹的先後順序沒有改變,而根結點的位置對應了“前”“中”“後”三個位置)
  • 題目描述

  • 樹的重建(Reconstruction of the tree)

    • 現有兩個結點序列,分別是對同一個二叉樹進行前序遍歷和中序遍歷的結果。請編寫一個程序,輸出該二叉樹按後序遍歷時的結果。

    • 輸入

      • 第1行輸入二叉樹的結點數n。

      • 第2行輸入前序遍歷的結點編號序列,相鄰編號用空格隔開。

      • 第3行輸入中序遍歷的結點編號序列,相鄰編號用空格隔開。

      • 結點編號爲從1至n的整數。請注意,1不一定是根結點。

    • 輸出

      • 在1行中輸出按後序遍歷時的結點編號序列。相鄰結點編號之間用1個空格隔開。

    • 限制

      • 1≤結點數≤100

  • 解題思路

  • 輸出未知二叉樹的後序遍歷
  • 這個問題可以變形爲:
    • 輸出當前二叉樹左子樹的後序遍歷;
    • 輸出當前二叉樹右子樹的後序遍歷;
    • 輸出當前二叉樹的根結點。
  • 根據已知的前序遍歷和後序遍歷,我們可以知道:
    • 當前二叉樹的根結點 -> 二叉樹的前序遍歷的首元素;
    • 當前二叉樹的左右子樹 -> 二叉樹的中序遍歷的位於根結點左右兩邊的元素集合。
  • 找到根結點的過程我們可以通過前序遍歷的特性O(1)的查詢。
  • 對於尋找左右子樹的過程,我們也可以通過預處理O(1)的查詢。
    • 預處理:將中序遍歷中的元素下標記錄下來,排序後便可以O(1)的查詢了。
  • 代碼實現

  • #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int size = 150;
    int n,Preorder[size],Inorder[size];
    struct data {
        int k,i;
        data() {
        }
        data(int a,int b) {
    	k = a; i = b;
        }//結構體的構造函數 
    } temp[size];
    bool cmp(data a,data b) {
        return a.k < b.k;
    }//結構體的比較函數 
    void make_Postorder(int l1,int r1,int l2,int r2) {
        if(l1 == r1) cout << Preorder[l1] << ' ';//遞歸出口:如果到達葉結點則退出 
        else {
    	int root = Preorder[l1];
    	int divide = temp[root].i;//記錄此子樹中根在中序遍歷中的位置 
    	int size1 = divide - l2;//記錄此子樹中左子樹的結點個數 
    	make_Postorder(l1 + 1,l1 + size1,l2,divide - 1);
    	make_Postorder(l1 + size1 + 1,r1,divide + 1,r2);
    	cout << root << ' ';
        }
        return;
    }
    int main() {
        memset(Preorder,0,sizeof(Preorder));//初始化 
        memset(Inorder,0,sizeof(Inorder));
        cin >> n;
        for(int i = 1;i <= n;i++)
            cin >> Preorder[i];
        for(int i = 1;i <= n;i++) {
        	cin >> Inorder[i];
    		temp[i] = data(Inorder[i],i);
        }	
        sort(temp + 1,temp + 1 + n,cmp);
        make_Postorder(1,n,1,n);
        return 0; 
    }

     

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