簡體   English   中英

如何在給定深度和后序遍歷的情況下構造一棵樹,然后打印其前序遍歷

[英]How to construct a tree given its depth and postorder traversal, then print its preorder traversal

我需要構造一棵給定深度和后序遍歷的樹,然后我需要生成相應的前序遍歷。 例子:

Depth: 2 1 3 3 3 2 2 1 1 0
Postorder: 5 2 8 9 10 6 7 3 4 1
Preorder(output): 1 2 5 3 6 8 9 10 7 4

我定義了兩個包含后序序列和深度的 arrays。 在那之后,我想不出一個算法來解決它。

這是我的代碼:

int postorder[1000];
int depth[1000];
string postorder_nums;
getline(cin, postorder_nums);
istringstream token1(postorder_nums);
string tokenString1;
int idx1 = 0;
while (token1 >> tokenString1) {
    postorder[idx1] = stoi(tokenString1);
    idx1++;
}
string depth_nums;
getline(cin, depth_nums);
istringstream token2(depth_nums);
string tokenString2;
int idx2 = 0;
while (token2 >> tokenString2) {
    depth[idx2] = stoi(tokenString2);
    idx2++;
}
Tree tree(1);

我不會給你代碼,而是一些提示如何解決這個問題。

首先,對於后序圖處理,您首先訪問子節點,然后打印(處理)節點的值。 因此,樹或子樹父是在其(子)樹中處理的最后一件事。 我將 10 替換為 0 以獲得更好的縮進:

2 1 3 3 3 2 2 1 1 0
--------------------
5 2 8 9 0 6 7 3 4 1

如上所述,深度為 0 的節點或根是最后一個。 讓我們將所有其他節點降低 1 級:

2 1 3 3 3 2 2 1 1 0
-------------------
                  1
5 2 8 9 0 6 7 3 4 

現在識別深度為 1 的所有節點,並降低所有深度不為 0 或 1 的節點:

2 1 3 3 3 2 2 1 1 0
-------------------
                  1
  2           3 4 
5   8 9 0 6 7 

如您所見,(5,2)在一個子樹中,(8,9,10,6,7,3)在另一個子樹中,(4)是單節點子樹。 換句話說,2的左邊都是它的子樹,2的右邊和3的左邊都是3的子樹,3到4之間的都是4的子樹(這里:空)。

現在讓我們以類似的方式處理深度 3:

2 1 3 3 3 2 2 1 1 0
-------------------
                  1
  2           3 4 
5         6 7 
    8 9 0  
  • 2 是 2 的父級;
  • 6 是 8、8、10 的父級;
  • 3 是 6,7 的父母;

或非常明確:

2 1 3 3 3 2 2 1 1 0
-------------------
                  1
   /           / /
  2           3 4 
 /         / /
5         6 7 
     / / /
    8 9 0  

這就是您可以從您擁有的數據中構建一棵樹的方法。

編輯

顯然,這個問題可以很容易地通過遞歸來解決。 在每個步驟中,您找到最低深度,打印節點,並為其每個子樹遞歸調用相同的 function 作為其參數,其中子樹是通過查找 current_depth + 1 來定義的。如果深度作為另一個參數傳遞,它可以省去計算最低深度的必要性。

您實際上可以在不構建樹的情況下執行此操作。

首先請注意,如果您反轉后序序列,您會得到一種前序序列,但訪問的孩子順序相反。 所以我們將使用這個事實並從后到前迭代給定的 arrays,我們還將從后到前將值存儲在 output 中。 這樣至少兄弟姐妹的順序會正確。

因此,我們從輸入中獲得的第一個值將始終是根值。 顯然,我們不能將此值存儲在 output 數組的末尾,因為它確實應該排在第一位。 但是我們將把這個值放在一個堆棧上,直到所有其他值都被處理完。 對於后面跟着“更深”值的任何值都會發生同樣的情況(同樣:我們正在以相反的順序處理輸入)。 但是一旦我們找到一個不深的值,我們就會將堆棧的一部分刷新到 output 數組中(也從后到前填充它)。

處理完所有值后,我們只需要將堆棧中的剩余值刷新到 output 數組中。

現在,我們可以在這里優化空間使用:當我們從后面填充 output 數組時,我們在其前面有空閑空間用作該算法的堆棧空間。 這有一個很好的結果,當我們到達最后時,我們不再需要刷新堆棧,因為它已經存在於 output 中,每個值都應該存在。

這是該算法的代碼,其中我沒有包含輸入集合,顯然您已經在使用它:

// Input example
int depth[] = {2, 1, 3, 3, 3, 2, 2, 1, 1, 0};
int postorder[] = {5, 2, 8, 9, 10, 6, 7, 3, 4, 1};
// Number of values in the input
int n = sizeof(depth)/sizeof(int);

int preorder[n]; // This will contain the ouput
int j = n; // index where last value was stored in preorder
int stackSize = 0; // how many entries are used as stack in preorder
for (int i = n - 1; i >= 0; i--) {
    while (depth[i] < stackSize) {
        preorder[--j] = preorder[--stackSize]; // flush it
    }
    preorder[stackSize++] = postorder[i]; // stack it
}
// Output the result:
for (int i = 0; i < n; i++) {
    std::cout << preorder[i] << " ";
}
std::cout << "\n";

該算法的輔助空間復雜度為 O(1)——因此不計算輸入所需的 memory 和 output——並且時間復雜度為 O(n)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM