面試題6 重建二叉樹

2021-08-15 02:25:10 字數 1584 閱讀 4276

題目:輸入某二叉樹的前序遍歷和中序遍歷的結果。請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列和中序遍歷序列,則重建出如圖所示的二叉樹並輸出它的頭節點。二叉樹結點的定義如下

在二叉樹的前序遍歷序列中,第乙個數字總是樹的根結點的值。但在中序遍歷序列中,根結點的值在序列的中間,左子樹的結點的值位於根結點的值的左邊,而右子樹的結點的值位於根結點的值的右邊。因此我們需要掃瞄中序遍歷序列,才能找到根結點的值。

如圖所示

前序遍歷序列的第乙個數字1就是根結點的值,掃瞄中序遍歷序列,就能確定根結點的值的位置。根據中序遍歷特點,在根結點的值1前面的3個數字都是左子樹節點的值,位於1後面的數字都是右子樹結點的值。

由於在中序遍歷序列中,有3個數字是左子樹結點的值,因此左子樹總共有3個左子結點,同樣,在前序遍歷的序列中,根結點後面的3個數字就是3個左子樹結點的值,再後面的所有數字都是右子樹結點的值。這樣我們就在前序遍歷和中序遍歷兩個序列中,分別找到了左右子樹對應的子串行。

既然我們已經分別找到了左右子樹的前序遍歷序列和中序遍歷序列,我們可以用同樣的方法分別去構建左右子樹。也就是說,接下來的事情可以用遞迴的方法去完成。

在想清楚如何在前序遍歷和中序遍歷的序列中確定左右子樹的子串行之後,我們可以寫出如下的遞迴**:

binarytreenode* construct(int* preorder, int inorder, int

length)

binarytreenode* constructcore

//在中序遍歷中找到根結點的值

int* rootinorder = startinorder;

while(rootinorder <= endinorder && *rootinorder != rootvalue)

++ rootinorder;

if(rootinorder == endinorder && *rootinorder != rootvalue)

throw std::exception("invalid input.");

int lefelength = rootinorder - startinorder;

int*leftpreorderend = startpreorder + leftlength;

if(leftlength > 0)

if(leftlength < endpreorder - startpreorder)

return root;

}

在函式constructcore中,我們先根據前序遍歷序列的第乙個數字建立根結點,接下來在中序遍歷序列中找到根結點的位置,這樣就能確定左右子樹結點的數量。在前序遍歷和中序遍歷的序列中劃分了左右子樹結點的值之後,我們就可以遞迴的呼叫函式constructcore,去分別構建它的左右子樹。

面試題6 重建二叉樹

面試題6 題目 輸入某二叉樹的前序遍歷和中序遍歷的結果,重建出該二叉樹。不包含重複數字。前序遍歷的第乙個結果就是根節點,中序遍歷中根節點前面的節點就是左子樹,後面的節點就是右子樹。然後遞迴的構建左右子樹。binarytreenode constructbinarynode int startpreo...

面試題6 重建二叉樹

templatestruct binarytreenode 對比二叉樹的圖形和其兩個遍歷序列來看,可以發現在前序遍歷序列中第乙個數字總是二叉樹的根節點的值,然後在中序遍歷序列中找到該值,它的前面就是它左子樹上節點值的集合,後面就是它右子樹上節點值的集合。由此就可以遞迴地在這兩個集合中建立二叉樹。bi...

面試題6 重建二叉樹

二叉樹中最重要的操作莫過於遍歷,即按照某一順序訪問樹中的所有結點。以下這三種遍歷都有遞迴和迴圈兩種實現方法,每一種遍歷的遞迴都要比迴圈實現簡潔地多。前序遍歷首先訪問根結點然後遍歷左子樹,最後遍歷右子樹。在遍歷左 右子樹時,仍然先訪問根結點,然後遍歷左子樹,最後遍歷右子樹。遞迴實現 void preo...