定義:
中綴表達式: 在通常的表達式中,二元運算符總是置於與之相關的兩個運算對象之間,這種表示法也稱為中綴表達式
后綴表達式: 又叫逆波蘭表達式 ,不包含括號,運算符放在兩個運算對象的后面,所有的計算按運算符出現的順序,嚴格從左向右進行(不再考慮運算符的優先規則,如:(2 + 1) * 3 , 即2 1 + 3 *
一個字符串表達式s = “9 + ( 3 - 1 ) * 3 + 10 / 2”)求值的過程分為兩步
(一) 將 中綴表達式s變為后綴表達式s_after = "9 3 1 - 3 * + 10 2 / +",具體的規則如下 :
首先維護兩個空棧,(stack_exp)存放逆波蘭表達式,(stack_ops)暫存操作符,運算結束后stack_ops必為空
循環遍歷字符串(將表達式分為四種元素 1、數值; 2、操作符; 3、 左括號; 4、右括號),具體情況如下
1、遇到數值, 將該值入棧stack_exp
2、遇到左括號, 將左括號入棧stack_ops
3、遇到右括號,將stack_ops中的操作符從棧頂依次出棧並入棧stack_exp, 直到第一次遇到左括號終止操作(注意: 該左括號出棧stack_ops但不入棧stack_exp)至此消除表達式中的一對括號
4、遇到四則運算操作符號(+ - * /)
4-1、 如果stack_ops為空, 操作符入棧stack_ops
4-2、 如果stack_ops不空,將stack_ops棧頂操作符與遍歷到的操作符(op)比較:
4-2-1: 如果stack_ops棧頂操作符為左括或者op優先級高於棧頂操作符優先級, op入棧stack_ops,當前遍歷結束
4-2-2: 如果op優先級小於或者等於stack_ops棧頂操作符, stack_ops棧頂操作符出棧並入棧stack_exp,重復4-1、 4-2直到op入棧stack_ops
5、字符串遍歷結束后如果stack_ops棧不為空,則依次將操作符出棧並入棧stack_exp
python代碼實現如下:
ops_rule = { '+': 1, '-': 1, '*': 2, '/': 2 } def middle_to_after(s): expression = [] ops = [] ss = s.split(' ') for item in ss: if item in ['+', '-', '*', '/']: while len(ops) >= 0: if len(ops) == 0: ops.append(item) break op = ops.pop() if op == '(' or ops_rule[item] > ops_rule[op]: ops.append(op) ops.append(item) break else: expression.append(op) elif item == '(': ops.append(item) elif item == ')': while len(ops) > 0: op = ops.pop() if op == '(': break else: expression.append(op) else: expression.append(item) while len(ops) > 0: expression.append(ops.pop()) return expression
(二) 將后綴表達式s_after = "9 3 1 - 3 * + 10 2 / +" 求值,具體的規則如下 :
初始化一個空棧stack_value,用於存放數值
循環s_after
1、 如果遇到數字,入棧stack_value;
2、 如果遇到運算符, 從stack_value中依次出棧兩個數(先出棧的在右, 后出棧的在左)連同遍歷到的運算符組成二目運算,求值后將結果壓棧stack_value
3、 繼續遍歷下一個元素,直到結束
遍歷完后stack_value中的結果便是表達式的值
python代碼實現如下:
def expression_to_value(expression):
stack_value = []
for item in expression:
if item in ['+', '-', '*', '/']:
n2 = stack_value.pop()
n1 = stack_value.pop()
result = cal(n1, n2, item)
stack_value.append(result)
else:
stack_value.append(int(item))
return stack_value[0]
def cal(n1, n2, op):
if op == '+':
return n1 + n2
if op == '-':
return n1 - n2
if op == '*':
return n1 * n2
if op == '/':
return n1 / n2
if __name__ == '__main__':
expression = middle_to_after('9 + ( 3 * ( 4 - 2 ) ) * 3 + 10 / 2')
value = expression_to_value(expression)
print value
