字尾表示式
中綴即我們平時用的數學表示式,其遞迴定義為中綴表示式 運算子 中綴表示式。舉例:1+2,(1+2)*(3+4).這種表示式便於直觀理解但是不方便計算機計算。後來有波蘭人發明了字首,字尾表示式。字首表示式也叫波蘭式,字尾表示式也叫逆波蘭式。前字尾表示式經常作為棧在優先順序的應用的例題。
字首表示式遞迴定義為運算子 字首表示式 字首表示式。
字首計算方式即將運算子最右邊兩個放一起計算。
例題1:中綴表示式:1+((2+3)*4)-5,其對應字首為- + 1 * + 2 3 4 5.字首求值方式為每次取兩個數字進行計算。具體如下(宣告兩個stack, s1和s2)
s1s2
說明- + 1 * + 2 3 4 5
初始- + 1 * + 2 3 4
5- + 1 * + 2 3
4 5- + 1 * + 2
3 4 5
- + 1 * +
2 3 4 5
- + 1 *
5 4 5
2 3出棧,做加法再push回去
- + 1
20 5
5 4出棧,做乘法再push回去
- +1 20 5
-21 5
20 1出棧,做加法再push回去
1621 5出棧,做加法再push回去
最後結果16.
可見字首表示式通過棧保證每次都是當前優先順序最高的兩個做運算,也可以理解為保證先計算當前子字首表示式。py**如下:
def calpre(number):
stack =
while number:
if number[-1].isdigit():
number.pop()
else:
a = stack[-1]
b = stack[-2]
stack.pop()
stack.pop()
if number[-1] == '+':
elif number[-1] == '-':
elif number[-1] == '*':
else:
number.pop()
return stack[0]
那麼先問問題來了,怎樣將中綴變字首?流程如下(摘抄自
1.初始化兩個棧:運算子棧s1和儲存中間結果的棧s2;
2.從右至左掃瞄中綴表示式;
3.遇到運算元時,將其壓入s2;
4.遇到運算子時,比較其與s1棧頂運算子的優先順序:
4.1. 如果s1為空,或棧頂運算子為右括號「)」,則直接將此運算子入棧;(右括號出現為了等待左括號,另外如果棧頂是右括號,此時開始計算子綴表示式)
4.2. 否則,若優先順序比棧頂運算子的較高或相等,也將運算子壓入s1;
4.3. 否則,將s1棧頂的運算子彈出並壓入到s2中,再次轉到(4-1)與s1中新的棧頂運算子相比較;(只有當 當前運算子級別比棧頂的低時才把棧頂的彈出,這樣保證低級別盡可能留在最後計算,這句話純屬個人理解)
5.遇到括號時:
5.1. 如果是右括號「)」,則直接壓入s1;
5.2.如果是左括號「(」,則依次彈出s1棧頂的運算子,並壓入s2,直到遇到右括號為止,此時將這一對括號丟棄;(一對括號內部是乙個子表示式,也是乙個子字首表示式,雖然物理上是一串字串,但是邏輯上就是乙個數字因此需要將其算完)
6.重複步驟(2)至(5),直到表示式的最左邊;
7.將s1中剩餘的運算子依次彈出並壓入s2;
8.依次彈出s2中的元素並輸出,結果即為中綴表示式對應的字首表示式。
這裡邊最關鍵的是棧的應用,如何通過棧安排好不同優先順序的運算子。
例題2:已知中綴表示式:1+((2+3)*4)-5 求字首表示式。
當前符號
s1(符號棧)
s2(暫存結果)說明5
5--5
符號棧空,直接push進去))-
5)直接push進去4)-
4 5)直接push進去
**)-
4 5棧頂是右括號,*直接push進去
))*)-
4 5)直接push進去
3)*)-
3 4 5
3直接push進去
++)*)-
3 4 5
+直接push進去
2+)*)-
2 3 4 5
2 直接push進去
(*)-
+ 2 3 4 5
遇到(,就把符號棧依次出棧直到遇到),)丟棄(-
* + 2 3 4 5
再次遇到(,就把符號棧依次出棧直到遇到),)丟棄+±
* + 2 3 4 5
棧頂優先順序不低於+ 直接入棧1±
1* + 2 3 4 5
1入棧-+1* + 2 3 4 5
剩餘依次入棧
另外如果僅僅為了手工生成字首,可以這樣做:1+((2+3)*4)-5
還是從右往左,遇到第乙個符號是-,可以把中綴表示式分成兩個部分:
1+((2+3)*4)-5,那麼其字首表示式為 :
-①1+((2+3)*4)②5
下一步是把①②分別轉化成中綴表示式,②不用轉,直接看①
①可以寫成:
+③1 ④((2+3)*4))
之後每一步如法炮製……
下面是演算法的**實現:
level =
def midtopre(str):
symbol,number = ,
for i in range(len(str)-1,-1,-1):
s = str[i]
if s.isdigit():
else:
if not symbol or s == ')' or symbol[-1] == ')':#左括號或者symbol空直接入棧
elif s == '(':
while symbol[-1] != ')':
symbol.pop()
symbol.pop()
else:
while symbol and level[s] < level[symbol[-1]]:
symbol.pop()
while symbol:
symbol.pop()
number.reverse()
return number
字首變中綴的過程類似字首求值計算。每次彈出兩個,當當前運算子高於上次運算子時加上括號。
例題:-+1* + 2 3 4 5 變中綴
當前符號
stack說明5
544 53
3 4 5
22 3 4 5
+2+3 4 5
*(2+3)*4 5
*高於+,加上括號
11 (2+3)*4 5
+1+(2+3)*4 5
-1+(2+3)*4 - 5
**如下:
def pretomid(prelist):
stack =
last = ''
for i in range(len(prelist)-1,-1,-1):
s = prelist[i]
if s.isdigit():
else:
if last != '' and level[s] > level[last]:
stack[-1] = ')'+stack[-1]+'('#最後要翻轉
a = stack[-1]
b = stack[-2]
stack.pop()
stack.pop()
last = s
return stack[0][::-1]
字尾表示式顧名思義,運算子在 後邊,定義為 字尾表示式 運算子 字尾表示式。例如:1+((2+3)×4)-5的字尾表示式為1 2 3 + 4 × + 5 -。這個求值和字首類似 ,不再贅述。
1.初始化兩個棧:運算子棧s1和儲存中間結果的棧s2;
2.從左至右掃瞄中綴表示式;
3.遇到運算元時,將其壓入s2;
4.遇到運算子時,比較其與s1棧頂運算子的優先順序:
4.1. 如果s1為空,或棧頂運算子為左括號「(」,則直接將此運算子入棧;
4.2. 否則,若優先順序比棧頂運算子的較高(不含 相等),也將運算子壓入s1;
4.3. 否則,將s1棧頂的運算子彈出並壓入到s2中,再次轉到(4-1)與s1中新的棧頂運算子相比較;(只有當 當前運算子級別比棧頂的低時才把棧頂的彈出,這樣保證低級別盡可能留在最後計算,這句話純屬個人理解)
5.遇到括號時:
5.1. 如果是左括號「(」,則直接壓入s1;
5.2.如果是右括號「)」,則依次彈出s1棧頂的運算子,並壓入s2,直到遇到右括號為止,此時將這一對括號丟棄;
6.重複步驟(2)至(5),直到表示式的最左邊;
7.將s1中剩餘的運算子依次彈出並壓入s2;
8.依次彈出s2中的元素並輸出,結果即為中綴表示式對應的字首表示式。
注意與字首的區別。
略
中綴表示式 字首表示式 字尾表示式
中綴表示式 中綴記法 中綴表示式是一種通用的算術或邏輯公式表示方法,操作符以中綴形式處於運算元的中間。中綴表示式是人們常用的算術表示方法。雖然人的大腦很容易理解與分析中綴表示式,但對計算機來說中綴表示式卻是很複雜的,因此計算表示式的值時,通常需要先將中綴表示式轉換為字首或字尾表示式,然後再進行求值。...
中綴表示式 字尾表示式 字首表示式
正如我們常常潛意識認為我們所說的數字都是十進位制,對於數字的其他進製感覺不正確一樣,其實只是我們不熟悉而已,其他進製其實也不過就是一種對資料的表達方式而已。對於我們的表示式也是一樣。eg 表示式2 3 5 7 我們上面所看到的也就是我們平時常用的書寫表示式的方式就是我們所謂的 中綴表示式 字首表示式...
字首表示式 中綴表示式 字尾表示式。
表示式 就是式子。是由數字 算符 數字分組符號 自由量和約束量組成的。人們一般習慣寫出來的式子,叫做中綴表示式。因為在計算機中,不方便表達 數字分組符號。所以 波蘭人發明了一種把去符號化的表示式。字首表示式 字首表示式 沒有括號,算符在前 數字在後。波蘭數學家發明,為了紀念,又叫做波蘭式。跟其對應,...