如何利用棧解決問題。html
Ref: 如何在程序中將中綴表達式轉換爲後綴表達式?算法
本文的引伸:如何手寫語法分析器數據結構
「9+(3-1)*3+10/2」 --> 「9 3 1-3*+ 10 2/+」app
從左到右遍歷中綴表達式的每一個數字和符號,post
如果數字就輸出,即成爲後綴表達式的一部分;spa
如果符號,則判斷其與棧頂符號的優先級,.net
是右括號或優先級低於棧頂符號(乘除優先加減)code
一直到最終輸出後綴表達式爲止。orm
1. 初始化一空棧,用來對符號進出棧使用。htm
2. 第一個字符是數字9,輸出9,後面是符號「+」,進棧。
3. 第三個字符是「(」,依然是符號,因其只是左括號,還未配對,故進棧。
4. 第四個字符是數字3,輸出,總表達式爲9 3,接着是「-」進棧。
5. 接下來是數字1,輸出,總表達式爲9 3 1,後面是符號「)」,此時,咱們須要去匹配此前的「(」,因此棧頂依次出棧,並輸出,直到「(」出棧爲止。此時左括號上方只有「-」,所以輸出「-」,總的輸出表達式爲9 3 1 -
6. 接着是數字3,輸出,總的表達式爲9 3 1 - 3 。緊接着是符號「*」,由於此時的棧頂符號爲「+」號,優先級低於「*」,所以不輸出,進棧。
7. 以後是符號「+」,此時當前棧頂元素比這個「+」的優先級高,所以棧中元素出棧並輸出(沒有比「+」號更低的優先級,因此所有出棧),總輸出表達式爲 9 3 1 - 3 * +;而後將當前這個符號「+」進棧。也就是說,前6張圖的棧底的「+」是指中綴表達式中開頭的9後面那個「+」,而下圖中的棧底(也是棧頂)的「+」是指「9+(3-1)*3+」中的最後一個「+」。
8. 緊接着數字10,輸出,總表達式變爲9 3 1-3 * + 10。
9. 最後一個數字2,輸出,總的表達式爲 9 3 1-3*+ 10 2
10. 因已經到最後,因此將棧中符號所有出棧並輸出。最終輸出的後綴表達式結果爲 9 3 1-3*+ 10 2/+
整個過程,都充分利用了找的後進先出特性來處理,理解好它其實也就理解好了棧這個數據結構。
import logging class Stack: def __init__(self): self.items = [] def isEmpty(self): return self.items == [] def push(self, item): logging.info("Info: push {}".format(item)) self.items.append(item) def pop(self): if True == self.isEmpty(): logging.info("Info: it's empty.") return None return self.items.pop() def peek(self): if True == self.isEmpty(): logging.info("Info: it's empty.") return None return self.items[-1] def size(self): return len(self.items) def __str__(self): return "{}".format(self.items) logging.basicConfig(level=logging.INFO) # 「9+(3-1)*3+10/2」 --> 「9 3 1-3*+ 10 2/+」 def infixToPostfix(infixexpr): prec = {} prec["*"] = 3 prec["/"] = 3 prec["+"] = 2 prec["-"] = 2 prec["("] = 1 # 只有符號才須要「棧' opStack = Stack() postfixList = [] tokenList = infixexpr.split() for token in tokenList: if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789": postfixList.append(token) elif token == '(': opStack.push(token) elif token == ')': # do...while, 把括號區間的符號都輸出 while True: topToken = opStack.pop() if topToken == '(': break postfixList.append(topToken) else: # 由於符號只有兩個優先級別, # +來了,確定弱於棧底元素;」先處理遺留問題」再入棧 # *來了,要麼弱於棧底元素;要麼更厲害,但反正仍是要入棧 while (not opStack.isEmpty()) and (prec[opStack.peek()] >= prec[token]): # 這裏就是「處理遺留問題」 postfixList.append(opStack.pop()) opStack.push(token) # 「處理遺留問題」 while not opStack.isEmpty(): postfixList.append(opStack.pop()) return " ".join(postfixList)
print(infixToPostfix("A * B + C * D")) print(infixToPostfix("( A + B ) * C - ( D - E ) * ( F + G )"))
End.