演算法 二叉樹的恢復

2021-10-23 06:10:35 字數 3282 閱讀 7183

3、根據中序和後序遍歷結果恢復二叉樹

二叉樹是乙個極為重要的資料結構,對它的掌握程度反映了反映了我們資料結構的掌握程度,尤其是一些大公司在面試非科班出身的程式設計師的時候就會出一些類似於二叉樹恢復的題目來試探我們。

先來看一下這棵二叉樹,我們以他為例

1

2 3

4 5 6 7

再看一下遍歷規則:

前序遍歷:根-左-右  

中序遍歷:左-根-右

後續遍歷:左-右-根

遍歷結果:

前序遍歷:1 2 4 5 3 6 7

中序遍歷:4 2 5 1 6 3 7

後續遍歷:4 5 2 6 7 3 1

二叉樹不同方式的遍歷各有特點,主要是如下三點:

前序遍歷:第乙個元素是根節點

中序遍歷:根節點左側為左子樹,右側為右子樹

後續遍歷:最後乙個元素是根節點

根據二叉樹的前序遍歷和中序遍歷的特點,我們可以使用遞迴方法對樹進行恢復

前序遍歷:1 2 4 5 3 6 7

中序遍歷:4 2 5 1 6 3 7

以上面舉例,根據前序遍歷,我們知道根節點為1,左子樹元素為 4 2 5,右子樹元素為6 3 7

根據前序遍歷的結果和後序遍歷的結果,我們還知道,左子樹的前序遍歷和中序遍歷結果為:

前序遍歷:2 4 5

中序遍歷:4 2 5

於是,我們知道根節點的左兒子為左子樹的根節點,也就是2

我們構造到這一步的樹是這樣的

1

2

同樣,右子樹的前序遍歷和後序遍歷的結果集為:

前序遍歷:3 6 7

中序遍歷:6 3 7

我們又得到結論,3是根節點的右子樹的的根節點。於是我們構造了這樣乙個樹

1

2 3

然後,我們遞迴的進行樹的構造,就得到了乙個完整的二叉樹。

可見問題的關鍵就是找到根節點,確定左右子樹,對左右子樹進行遞迴恢復!

/**

* * @param preorder 先序遍歷結果集

* @param prestart 本段先序遍歷起始位置

* @param preend 本段先序遍歷終止位置

* @param inorder 中序遍歷結果集

* @param instart 本段中序遍歷起始位置

* @param inend 本段中序遍歷終止位置

* @return 構造的二叉樹

*/public treenode rebuildtreefromprein

(int

preorder,

int prestart,

int preend,

int[

] inorder,

int instart,

int inend)

int headval=preorder[prestart]

; treenode head=

newtreenode

(headval)

;int leftsize=0;

//左子樹大小

for(

int i=instart;i<=inend;i++

) leftsize++

;//當前左子樹大小

}//注意左子樹前序遍歷的起始位置為當前左子樹起始位置+1,終止位置為當前左子樹起始位置+左子樹大小

//左子樹中序遍歷起始位置為中序遍歷的左子樹起始位置,結束位置為原來根節點位置的前乙個位置,也就是instart+leftsize-1

head.left=

rebuildtreefromprein

(preorder,prestart+

1,prestart+leftsize,inorder,instart,instart+leftsize-1)

; head.right=

rebuildtreefromprein

(preorder,prestart+leftsize+

1,preend,inorder,instart+leftsize+

1,inend)

;return head;

}

根據中序和後序遍歷恢復二叉樹的方式和2中方法幾乎一致,區別在於後序遍歷的頭部是後序遍歷最後乙個位置的元素。

/**

** @param inorder 中序遍歷結果集

* @param instart 本段中序遍歷起始位置

* @param inend 本段中序遍歷終止位置

* @param postorder 後續遍歷結果集合

* @param poststart 本段後序遍歷起始位置

* @param postend 本段後序遍歷終止位置

* @return

*/public treenode rebuildtreefrominpost

(int inorder,

int instart,

int inend,

int postorder,

int poststart,

int postend)

int headval=postorder[postend]

; treenode head=

newtreenode

(headval)

;int leftsize=0;

//左子樹元素個數

for(

int i=instart;i<=inend;i++

) leftsize++;}

head.left=

rebuildtreefrominpost

(inorder,instart,instart+leftsize,postorder,poststart,poststart+leftsize-1)

; head.right=

rebuildtreefrominpost

(inorder,instart+leftsize+

1,inend,postorder,poststart+leftsize,postend-1)

;return head;

}

二叉樹3(恢復二叉樹)

給一顆帶權 權值各不相同,都是小於10000的正整數 的二叉樹的中序和後序遍歷序列,找乙個葉子使得它到根的路徑上的權值盡可能小,如果有多解,取葉子權值小的。輸入中第一行為中序遍歷,第二行為後序遍歷。例如輸入 3 2 1 4 5 7 6 3 1 2 5 6 7 4 輸出輸入 7 8 11 3 5 16...

二叉樹的恢復

最近筆面老碰上這類題,老忘,因此寫個備忘。二叉樹的三種遍歷常用於恢復 先序,中序,後序。對於先 中,後 中這兩種組合,對任意二叉樹的恢復都有唯一解,但對先 後的情況則不是,這種情況下要滿足要求 對所有非葉節點,其兩個子節點都存在,也即,乙個節點要麼是葉節點,要麼有兩個節點。典型的恢復方法是遞迴建構節...

恢復二叉搜尋樹 二叉樹

給你二叉搜尋樹的根節點 root 該樹中的兩個節點被錯誤地交換。請在不改變其結構的情況下,恢復這棵樹。高階 使用 o n 空間複雜度的解法很容易實現。你能想出乙個只使用常數空間的解決方案嗎?示例 1 輸入 root 1,3,null,null,2 輸出 3,1,null,null,2 解釋 3 不能...