問題**於清華大學出版社2023年第二版《資料結構》,3.2節 表示式求值。書中採用了「算符優先法」並提供了演算法的偽**,本文是偽碼的python實現。
問題的簡要描述(具體可參考《資料結構》)
本文僅討論個位數的包含加減乘除和小括號的表示式,並規定表示式以『#』結束。
表示式例項:3*(7-2)#
不討論表示式語法錯誤的情況
θ₁\θ₂+-
*/()
#+>
>
<
<
<
>
>
->
>
<
<
<
>
>
*>
>
>
>
<
>
>
\>
>
>
>
<
>
>
(<
<
<
<
<
=)>
>
>
>
>
>
#<
<
<
<
<
=由於表示式以『#』結束,為了演算法簡潔,在表示式的最左邊虛設乙個『#』,構成一對。
為實現算符優先演算法,可以使用兩個工作棧。optr寄存運算子,opnd寄存運算元和運算結果。
演算法的基本思想為:
1.置運算元棧為空棧,表示式起始符『#』為運算子棧的棧底元素;
2.依次讀入表示式中的字元,若是運算元則進opnd棧;若是運算子,則和optr棧的棧頂運算子比較優先權後,進行相應操作,直至表示式求值完畢。
演算法的偽**表示
funcexp_reduced:operandtype;
inistack(optr);
push(optr,』#』);
instack(opnd);
read(w);
whilenot((w=』#』)and(gettop(optr)=』#』))do
ifwnotinopthenpush(opnd,w)
elsecaseprecede(gettop(optr),w)of
『<』:[push(optr,w); read(w)];
『=』:[x:=pop(optr); read(w)];
'『>』:[theta:=pop(optr); b=pop(opnd); a:=pop(opnd); push(opnd,operate(a,theta,b))]
endc;
return(gettop(opnd))
endf;
python實現
import numpy
defis_int
(x):
try:
int(x)
return
true
except valueerror:
return
false
#自定義函式,用於判斷字元是否為數字
defcalculate
(expression)
: change =
#將符號轉換為數字,用於對應二維陣列
prior = numpy.array([[
1,1,
-1,-
1,-1
,1,1
],[1
,1,-
1,-1
,-1,
1,1]
,[1,
1,1,
1,-1
,1,1
],[1
,1,1
,1,-
1,1,
1],[
-1,-
1,-1
,-1,
-1,0
,2],
[1,1
,1,1
,2,1
,1],
[-1,
-1,-
1,-1
,-1,
2,0]
])#用二維陣列表示符號間的優先關係,即上文中的**。
#其中1為》;0為=;-1為<;2用於佔位,也可以用於判斷表示式錯誤。在**中沒有討論表示式錯誤的情況。
operator =
['#'
] number =
#operator為偽碼中的optr棧,即運算子棧;number為opnd棧,即運算元棧。
i =0#通過下標遍歷字串
while
not(expression[i]
=='#'
and operator[-1
]=='#')
:if is_int(expression[i]):
) i +=
1elif prior[change[operator[-1
]]][change[expression[i]]]
==-1:
) i +=
1elif prior[change[operator[-1
]]][change[expression[i]]]
==0: operator.pop(
) i +=
1elif prior[change[operator[-1
]]][change[expression[i]]]
==1: op = operator.pop(
) b = number.pop(
) a = number.pop(
)str
(eval
(a + op + b)))
#計算a和b通過op運算子後的結果。我直接使用了eval函式,如果不用,可以寫四個判斷進行計算。
#需要注意的是eval接收的引數為字串,要將計算得到的結果轉化為字元再壓入棧內
return
int(number[-1
])#number內存放的是字元,需要轉化為數字
while
true
: string =
input
("input:"
)if string ==
"quit"
:break
else
:print
(calculate(string)
)#測試
個人想法
我在看到算符優先關係的**的時候挺迷惑的,帶入乙個例子模擬計算步驟就比較好理解了。
對於演算法的基礎實現,感覺python**量少的優勢完全沒有體現出來,c++也是差不多這樣寫的。不過如果直接用eval的話,python一行就可以出結果了。
參考資料
《資料結構》第二版 嚴蔚敏 吳偉民 編著 清華大學出版社 2023年6月 p45-47
簡單表示式求值
char evaluateexpression else c getchar gettop optr,e else gettop opnd,e return e 核心演算法如圖所示,基本思想是利用棧的基本性質和操作 數棧和算符棧兩棧分開 結合算符優先順序順序的二維陣列定義,完成基本算數表示式的核心演...
字尾表示式實現表示式求值
看到別人寫的乙個表示式求值程式,想到很久之前寫的乙個。中間有個字串轉數值型,可以用stringstream來實現或者c語言裡面的strtod直接得到 include include include include includeusing namespace std class data doubl...
簡單表示式求值(只有 )
題目如下 輸入僅有一行,為需要你計算的表示式,表示式中只包含數字 加法運算子 和乘法運算子 且沒有括號,所有參與運算的數字均為 0 到 2 31 1 之間的整數。輸入資料保證這一行只有 0 9 這 12 種字元。輸出格式 輸出只有一行,包含乙個整數,表示這個表示式的值。注意 當答案長度多於 4 位時...