在文章資料結構入門(一)棧的實現中,我們已經知道了如何去實現「棧」這個資料結構,並且介紹了乙個它的應用:數的進製轉換。在本文中,將會介紹棧的第二個應用,也就是棧在數學表示式求值中的應用。
我們分以下幾步對數學表示式進行求值。
先不著急明白上述術語,你看下去就會明白了。
以下是棧的python實現(stack.py),**如下:
# -*- coding: utf-8 -*-
class
empty
(exception)
:# error attempting to access an element from an empty container
pass
class
stack
:# initialize
def__init__
(self)
: self.__data =
# length of stack
def__len__
(self)
:return
len(self.__data)
# whether the stack is empty
defis_empty
(self)
:return
len(self.__data)==0
# push an element is stack
defpush
(self, e)
:# top element of stack
deftop
(self)
:if self.is_empty():
raise empty(
'stack is empty'
)return self.__data[-1
]# remove the top element of stack
defpop
(self)
:if self.is_empty():
raise empty(
'stack is empty'
)return self.__data.pop(
)# clear the stack
defclear
(self)
:while
not self.is_empty():
self.pop(
)
首先,我們來看一下數學表示式的三種形式:字首表示式,中綴表示式,字尾表示式。
**中綴表示式(infix expression)**就是我們平時常用的書寫方式,帶有括號。**字首表示式(prefix expression)**要求運算子出現在運算數字的前面,**字尾表示式(postfix expression)**要求運算子出現在運算數字的後面,一般這兩種表示式不出現括號。示例如下:
中綴表示式
字首表示式
字尾表示式
a + b * c + d
+ + a * b c d
a b c * + d +
(a + b) * (c + d)
* + a b + c d
a b + c d + *
a * b + c * d
+ * a b * c d
a b * c d * +
a + b + c + d
+ + + a b c d
a b + c + d +
一般在計算機中,為了方便對表示式求值,我們需要將熟悉的中綴表示式轉化為字尾表示式。
中綴表示式轉字尾表示式的演算法如下:
建立乙個空棧opstack,用於儲存運算子。建立乙個空的列表,用於儲存輸出結果。
將輸入的中綴表示式(字串形式)用字串的split方法轉化為乙個列表。
從左到右對該列表進行遍歷操作(元素為token),如下:
如果token為左小括號,則將它壓入(psuh)到opstack中。
如果token是 *, /, +, -, 中的乙個,則將其壓入(push)到opstack中。注意,先要移除那些運算優先順序大於等於該token的運算子,並將它們新增到輸出列表中。
上述過程的完整python**如下:
# -*- coding: utf-8 -*-
from stack import stack
# 中綴表示式轉化為字尾表示式
definfixtopostfix
(infixexpr)
: prec =
opstack = stack(
) postfixlist =
tokenlist = infixexpr.split(
)for token in tokenlist:
if token.isdigit()or
'.'in token:
elif token ==
'(':
opstack.push(token)
elif token ==
')':
toptoken = opstack.pop(
)while toptoken !=
'(':
toptoken = opstack.pop(
)else
:while
(not opstack.is_empty())
and(prec[opstack.top()]
>= prec[token]):
))opstack.push(token)
while
not opstack.is_empty():
))return
" ".join(postfixlist)
# inexpr = "( ( 1 + 2 ) * 3 ) * ( 3 - 1.2 )"
inexpr =
"10 + 3 * 5 / ( 16 - 4 )"
postexpr = infixtopostfix(inexpr)
print
(postexpr)
輸出結果如下:
10 3 5 * 16 4 - / +
當把中綴表示式轉化為字尾表示式之後,我們再利用棧對字尾表示式求值。其具體的演算法如下:
建立乙個棧來儲存待計算的運算數;
遍歷字串,遇到運算數則壓入棧中,遇到運算子則出棧運算數(2次),進行相應的計算,計算結果是新的運算元,壓入棧中,等待計算;
按上述過程,遍歷完整個表示式,棧中只剩下最終結果;
完整的python**如下:(接以上**)
# -*- coding: utf-8 -*-
from stack import stack
# 兩個數的運算, 除法時分母不為0
defoperate
(op, num1, num2)
:if num2 ==0:
raise zerodivisionerror
else
: res =
return res[op]
# 將字串轉化為浮點型或整型數字
defstr2num
(s):
if'.'
in s:
return
float
(s)else
:return
int(s)
# 字尾表示式求值
defevalpostfix
(e):
tokens = e.split(
)# 字尾表示式轉化為列表
s = stack(
)for token in tokens:
if token.isdigit()or
'.'in token:
# 如果當前元素是數字
s.push(str2num(token)
)elif token in
'+-*/'
:# 如果當前元素是運算子
op2 = s.pop(
) op1 = s.pop(
) s.push(operate(token, op1, op2)
)# 計算結果入棧
return s.pop(
)# inexpr = "( ( 1 + 2 ) * 3 ) * ( 3 - 1.2 )"
inexpr =
"10 + 3 * 5 / ( 16 - 4 )"
postexpr = infixtopostfix(inexpr)
print
(postexpr)
result = evalpostfix(postexpr)
print
(result)
輸出結果:
11.25請務必注意,我們輸入的中綴表示式中,每個運算子或運算子要用空格隔開。
3.9. infix, prefix and postfix expressions:
python演算法實戰系列之棧:
資料結構入門(二)棧的應用之數學表示式求值
在文章資料結構入門 一 棧的實現中,我們已經知道了如何去實現 棧 這個資料結構,並且介紹了乙個它的應用 數的進製轉換。在本文中,將會介紹棧的第二個應用,也就是棧在數學表示式求值中的應用。我們分以下幾步對數學表示式進行求值。先不著急明白上述術語,你看下去就會明白了。以下是棧的python實現 stac...
資料結構 棧的應用之表示式求值
任何乙個表示式都是由運算元 運算子和界限符組成的,我們稱它們為單詞。一般地,運算元既可以是常數也可以是被說明為變數或常量的識別符號 運算子可以分為算術運算子 關係運算子和邏輯運算子 基本界限符由左右括號和表示式結束符等。此處,我們討論簡單算術表示式的求值問題,這種表示式只含加 減 乘 除四種運算子以...
資料結構 棧應用
一 算術表示式的中綴表示 把運算子放在參與運算的兩個運算元中間的算術表示式稱為中綴表示式。例如 2 3 4 6 9 算術表示式中包含了算術運算子和算術量 常量 變數 函式 而運算子之間又存在著優先順序,不能簡單地進行從左到右運算,編譯程式在求值時,不能簡單從左到右運算,必須先算運算級別高的,再算運算...