題目連結:
題目大意:
給定一個中序運算式,請轉成後序運算式,並輸出於一行。每筆輸出之間要空一行。
對於每個中序運算式,保證為合法的運算式,並且會以每一行一個字元輸入進來。每一個運算式最多占50行,每個運算式之前必定有一個空行。
運算元為一位數數字,且運算子都為二元運算子( + - * / )。運算子的優先順序為:先乘除,後加減,並由左至右運算,括號最先算。
範例輸入:
2
(
3
+
2
)
*
5
3
+
2
範例輸出:
32+5*
32+
解題思維:
首先,先理解「中序運算式」、「後序運算式」到底是什麼:
「中序運算式」,即是我們一般會看見的運算式形式。例如:2+7 * 8,每個運算子都會被運算元所包圍(除非是一元運算子,或是括號)。
「後序運算式」,則是電腦方便運算的運算式形式。例如,上面的2+7 * 8的後序運算式為278 * +。而在生成後序運算式時,各個運算子的運算順序已經被考慮進去(包含括號),因此在裡面不會再看到括號的存在。
可是為何有中序、後序之差?這是因為,每個運算式都可化為一個樹,以上面的2+7 * 8為例,可化為:
如上圖,是一個二元樹(每個節點最多兩個子樹)。
我們常見的「中序運算式」便是這棵樹經由「中序探訪」的「路徑」。先走左子樹,接下來是自己,最後再走右子樹。
相似地,「後序運算式」為這棵樹的「後序探訪」。先走左子樹、再右子樹,最後才走根節點。
而中序轉後序不需要真的建一棵二元樹,再用後序探訪找路徑。只需要堆疊,在輸入的時候即可轉變成後序運算式。
以5+7-8 /(6+2)* 2為例:
先讀入5,一讀入數字即可把它放進後序運算式的結果之中。現結果為5,堆疊為空。
讀入+,放進堆疊裡。現結果為5,堆疊裡有+。
讀入7,結果為57,堆疊裡有+。
讀入-,判斷堆疊的頂端元素的優先順序,是否大於等於現在讀入的運算子之優先度。如果是,就一直把堆疊的頂端元素拿出,直到堆疊為空或是不符合為止。最後再放入現有的運算子。現結果為57+,堆疊裡有-。
讀入8,結果為57+8,堆疊裡有-。
讀入 / ,結果為57+8,堆疊裡有- / 。
讀入(,左括號很特別,要與右括號配對。結果為57+8,堆疊裡有- / (。
讀入6,結果為57+86,堆疊裡有- / (。
讀入+,結果為57+86,堆疊裡有- / (+。
讀入2,結果為57+862,堆疊裡有- / (+。
讀入),把堆疊的頂端元素拿出,直到遇見(。現結果為57+862+,堆疊裡有- / 。
讀入 * ,結果為57+862+ / ,堆疊裡有- * 。
讀入2,結果為57+862+ / 2,堆疊裡有- * 。
最後把堆疊清空,最終結果即為57+862+ / 2 * -,即是題目所求。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。