例如中綴表示式為a+b*c,其對應的字尾表示式是abc*+,首先將其轉化為全括號表示式(a+(b*c)),看表示式的右括號,如果把操作符*移到右括號的位置,替代它,再把左括號刪去,這個式子就可以變成字尾形式
字尾表示式的操作符要比運算元晚輸出,而實際掃瞄中綴表示式時,在碰到第二個運算元之前,已經掃瞄到了操作符,但是讀到操作符不能輸出,需要先把操作符暫存起來,而儲存的操作符,需要按照優先順序反轉次序輸出。考慮到這種反轉特性,我們用棧來儲存這些暫時還沒有處理的操作符。
而且有括號的情況下,括號內的操作符優先順序會變高。參考之前的全括號表示式法,字尾表示式中操作符應該出現在左括號對應的右括號的位置。所以遇到左括號,要標記下來,其後出現的操作符優先順序提公升了,一旦掃瞄到對應的右括號,就可以馬上輸出這個操作符。
所以,在從左到右逐個掃瞄字元的過程中,需要採用乙個棧暫存未處理的操作符。這樣棧頂操作符就是最近暫存進去的,當遇到乙個新的操作符,就需要跟棧頂的操作符比較一下優先順序,再進行處理。
演算法流程:
如果單詞是運算元,則直接新增到字尾表示式列表的末尾
如果單詞是左括號"(",則壓入opstack棧頂
如果單詞是右括號")",則反覆彈出opstack棧頂操作符,加入到輸出列表末尾,直到碰到左括號
如果但此時操作符"*/±",則壓入opstack棧頂(但在壓入前,需要比較其與棧頂操作符的優先順序,如果棧頂的高於或等於它,就要反覆彈出棧頂操作符,加入到輸出列表末尾,直到棧頂的操作符優先順序低於它)
程式如下:
from pythonds.basic.stack import stack
definfixtopostfix
(infixexpr)
:##記錄操作符優先順序,方便之後通過鍵值查詢
prec =
prec[
'*']=3
prec[
'/']=3
prec[
'+']=2
prec[
'-']=2
prec[
'(']=1
##創造堆疊和輸出序列
opstack = stack(
) postfixlist =
for token in infixexpr:
if token in
"abcdefghijklmnopqrstuvwxyz"
or token in
"0123456789"
:elif token ==
"(":
opstack.push(token)
elif token ==
")":
toptoken = opstack.pop(
)##首先要彈出,然後判斷
while toptoken !=
"(":
##正確的表示式在碰到右括號之前,堆疊中一定已經有了左括號
toptoken = opstack.pop(
)else
:while
(not opstack.isempty())
and(prec[opstack.peek()]
>= prec[token]):
))##同時實現了彈出和輸出功能
opstack.push(token)
while
not opstack.isempty():
))return
"".join(postfixlist)
print
(infixtopostfix(
'(a+(b*c))+d'
))
注意:遇到右括號")",首先操作是彈出,不管此時棧頂是否已經是左括號"(",其次才是判斷彈出的操作符是否為左括號"(",如果不是的話,將棧頂的操作符彈出,所以下一次進入迴圈時,已經是棧頂被彈出的狀態了。這點很關鍵。下面是我自己畫的一張程式執行的每一步細節解析:
資料結構與演算法 學習記錄(壹)
群集是一種結構化的資料型別。群集可以分為兩類 線性的和非線性的。線性群集是一張元素列表,表中的元素順次相連。線性群集中的元素通常由位置來決定次序 例如,第乙個元素 第二個元素 第三個元素,依次類推 在現實世界中,購物清單就是很好的線性群集例項。而在計算機世界中 當然這也是真實世界 則把陣列設計成線性...
資料結構與演算法學習記錄 快速排序
快速排序的基本思想 分治法,即,分解,求解,組合 分解 在無序區r low.high 中任選乙個記錄作為基準 通常選第乙個記錄,並記為pivot,其下標為pivotpos 以此為基準劃分成兩個較小的子區間r low,pivotpos 1 和r pivotpos 1 high 並使左邊子區間的所有記錄...
資料結構與演算法學習
我想重新學習一下資料結構與演算法,打好基礎。to measure is to know.我們用演算法複雜度t n 來表示演算法的效率,效能。t n 的取值 所有問題規模為n的問題例項中,將他們的計算成本進行總體的比較,取出最壞情況下的值。有幾點需要catch,1.演算法執行的時間,會根據程式語言,作...