已知前序(先序)與中序輸出後序

2021-08-21 15:11:55 字數 3509 閱讀 2030

已知前序(先序)與中序輸出後序:

前序:1, 2, 3, 4, 5, 6(根左右)

中序:3, 2, 4, 1, 6, 5(左根右)

分析:因為前序(根左右)最先出現的總是根結點,所以令root為前序中當前的根結點下標(並且同時把一棵樹分為左子樹和右子樹)。start為當前需要列印的子樹在中序中的最左邊的下標,end為當前需要列印的子樹在中序中最右邊的下標。遞迴列印這棵樹的後序,遞迴出口為start > end。i為root所表示的值在中序中的下標,所以i即是分隔中序中對應root結點的左子樹和右子樹的下標。

先列印左子樹,後列印右子樹,最後輸出當前根結點pre[root]的值。

輸出的後序應該為:3, 4, 2, 6, 5, 1(左右根)

#include #include #include #include using namespace std;

int pre = ;

int in = ;

void post(int root, int start, int end)

int main()

在參與過了美食節之後,小hi和小ho在別的地方又玩耍了一陣子,在這個過程中,小ho得到了乙個非常有意思的玩具——一棵由小球和木棍連線起來的二叉樹!

小ho對這棵二叉樹愛不釋手,於是給它的每乙個節點都標記了乙個標號——乙個屬於a..z的大寫字母,並且沒有任意兩個節點的標號是一樣的。小hi也瞅準了這個機會,重新鞏固了一下小ho關於二叉樹遍歷的基礎知識~就這樣,日子安穩的過了兩天。

這天,小ho正好在求解這棵二叉樹的前序、中序和後序遍歷的結果,但是卻在求出前序遍歷和中序遍歷之後不小心把二叉樹摔到了地上,小球和木棍等零件散落了一地!

小ho損失了心愛的玩具,正要嚎啕大哭起來,所幸被小hi發現了,勸說道:「別著急,這不是零件都還在麼?拼起來不就是了?」

「可是我忘記了二叉樹長什麼樣子了!」小ho沮喪道。

「這個簡單,你不是剛剛求出了這棵二叉樹的前序和中序遍歷的結果麼,利用這兩個資訊就可以還原出整棵二叉樹來哦!」

「這樣麼?!!」小ho止住了淚水,問道:「那要怎麼做呢?」

沒錯!小ho在這一周遇到的問題便是:給出一棵二叉樹的前序和中序遍歷的結果,還原這棵二叉樹並輸出其後序遍歷的結果。

「這可就要從頭說起了,我們先找一棵二叉樹作為例子吧!」小hi在紙上畫了畫,遞給了小ho。

「不妨假設你的二叉樹長成這個樣子~」小hi道。

「可是我的二叉樹並不是長成這個樣子啊!雖然我讀書少,但是你不要騙我好不好!」小ho一臉氣憤道。

「我都說了是假設!是為了能讓你明白如何通用的去解決這樣的問題!」小hi無奈道。

「好吧……你接著說。」小ho算是認可了這個說法。

「那麼對於這棵二叉樹,你先來計算一下它的前序遍歷和中序遍歷的結果吧!」小hi也是毫不含糊就開始下發任務。

「唔……前序遍歷是abdeghcfij,中序遍歷……我想想啊……是dbgehacijf!」小ho並沒有花費多長時間就給出了答案。

「你還記得前序遍歷的遞迴定義麼?」小hi點了點頭又繼續問道。

「是『根節點』+『左子樹的前序遍歷』+『右子樹的前序遍歷』!」小ho毫不猶豫的答道:「而在這裡體現出來就是『a'+『bdegh』+『cfij』」。

「那中序遍歷呢?」小hi繼續問道。

「是『左子樹的中序遍歷』+『根節點』+『右子樹的中序遍歷』!在這裡也就是『dbgeh』+『a』+『cijf』。」小ho這次花的時間更少了。

「還記得動態規劃時候我們一般處理的方法麼?我們這裡也可以這樣做哦,如果我們定義post_order(str1, str2)為一棵前序遍歷的結果為str1,中序遍歷的結果為str2的二叉樹的後序遍歷的結果的話,我們有沒有辦法把它化解成為子問題呢?」小hi道。

「讓我想想……」小ho拿出紙筆開始演算起來:「如果我要求解post-order(str1, str2)的話,首先不難發現,根據『前序遍歷』str1=『根節點』+『左子樹的前序遍歷』+『右子樹的前序遍歷』,我可以知道這棵二叉樹的根節點root便是str1的第乙個字元!」小ho道。

而我在知道了『根節點』root之後,我便可以利用『中序遍歷』str2=『左子樹的中序遍歷』+『根節點』+『右子樹的中序遍歷』,求解出『左子樹的中序遍歷』str2l和『右子樹的中序遍歷』str2r!

接下來,由於一棵子樹的前序遍歷和中序遍歷的長度相同,那麼仍然是根據『前序遍歷』str1=『根節點』+『左子樹的前序遍歷』+『右子樹的前序遍歷』,我可以知道從str1的第2個字元開始的str2l.length()個字元便是『左子樹的前序遍歷』str1l,而這之後的部分便是『右子樹的前序遍歷』str1r!」小ho說到這裡,頓了頓,希望從小hi處得到些反饋。

「沒錯!那你準備如何求解post_order(str1, str2)呢?」小hi肯定道。

「這只要根據之前求出的結果,和『後序遍歷』=『左子樹的後序遍歷』+『右子樹的後序遍歷』+『根節點』,便可以知道——post_order(str1, str2)=post_order(str1l, str2l)+post_order(str1r, str2r)+root這樣乙個式子來!而這個問題的規模——也就是二叉樹的大小,是一直在縮小的,所以是能夠這樣不斷的劃分做下去的!也就是說我之後可以將當前根節點的左子樹又拆分成為兩個問題來解決,一直到當前節點是葉子節點了為止!然後慢慢的將這些答案拼成上層的問題的答案,而這個過程只需要使用遞迴完成就可以了!」

「聽起來很容易的樣子呢!那你要不要趕緊去實現了演算法,算出你的寶貝二叉樹長什麼樣呢?」小hi滿意的點了點頭,隨即笑著問道。

「那是自然!」

close

輸入每個測試點(輸入檔案)有且僅有一組測試資料。

每組測試資料的第一行為乙個由大寫英文本母組成的字串,表示該二叉樹的前序遍歷的結果。

每組測試資料的第二行為乙個由大寫英文本母組成的字串,表示該二叉樹的中序遍歷的結果。

對於100%的資料,滿足二叉樹的節點數小於等於26。

輸出對於每組測試資料,輸出乙個由大寫英文本母組成的字串,表示還原出的二叉樹的後序遍歷的結果。

sample input

ab

ba

sample output

ba
#include #include #include #include using namespace std;

int pre[26*26*26];

int in[26*26*26];

void post(int root, int start, int end)

for(int i=0;i

post(0,0,s.length()-1);

printf("\n");

return 0;

}

已知前序(先序)與中序輸出後序

已知前序 先序 與中序輸出後序 前序 1,2,3,4,5,6 根左右 中序 3,2,4,1,6,5 左根右 分析 因為前序 根左右 最先出現的總是根結點,所以令root為前序中當前的根結點下標 並且同時把一棵樹分為左子樹和右子樹 start為當前需要列印的子樹在中序中的最左邊的下標,end為當前需要...

已知前序(先序)與中序輸出後序

已知前序 先序 與中序輸出後序 前序 1,2,3,4,5,6 根左右 中序 3,2,4,1,6,5 左根右 分析 因為前序 根左右 最先出現的總是根結點,所以令root為前序中當前的根結點下標 並且同時把一棵樹分為左子樹和右子樹 start為當前需要列印的子樹在中序中的最左邊的下標,end為當前需要...

已知前序(先序)與中序輸出後序

已知前序 先序 與中序輸出後序 前序 1,2,3,4,5,6 根左右 中序 3,2,4,1,6,5 左根右 分析 因為前序 根左右 最先出現的總是根結點,所以令root為前序中當前的根結點下標 並且同時把一棵樹分為左子樹和右子樹 start為當前需要列印的子樹在中序中的最左邊的下標,end為當前需要...