Python与数据结构[1] -> 栈/Stack[1] -> 中缀表达式与后缀表达式的转换和计算
中缀表达式与后缀表达式的转换和计算
目录
中缀表达式转换为后缀表达式的实现方式为:
- 依次获取中缀表达式的元素,
- 若元素为操作数(数字/字母等),则加入后缀表达式中
- 若元素为操作符,则压入栈中,此时对比入栈操作符与栈内元素的计算等级,等级大于或等于入栈元素的栈内操作符都将被弹出栈,加入到后缀表达式中
- 左括号直接入栈,优先级最高,不弹出栈内元素
- 右括号不入栈,而是弹出所有元素加入后缀表达式,直至遇见匹配的左括号,并弹出左括号但不加入后缀表达式中
- 当中缀表达式的元素耗尽后,依次弹出栈内元素加入到后缀表达式中。
代码实现过程如下,
完整代码
1 from linked_list_stack import Stack 2 3 SIGN = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 3} 4 5 6 def infix_to_postfix(expr): 7 global SIGN 8 out = [] 9 s = Stack() 10 for i in expr: 11 if i in SIGN.keys(): 12 # Pop all high level sign except left bracket 13 while s.top(): 14 if SIGN[s.top()] < SIGN[i] or s.top() == '(': 15 break 16 out.append(s.pop()) 17 # Push sign 18 s.push(i) 19 elif i == ')': 20 # Pop all sign until left bracket encountered 21 while s.top() != '(': 22 out.append(s.pop()) 23 # Pop left bracket 24 s.pop() 25 else: 26 # Push number 27 out.append(i) 28 29 while s.top(): 30 out.append(s.pop()) 31 return out 32 33 34 if __name__ == '__main__': 35 ep = 'a + b * c + ( d * e + f ) * g' 36 print(' '.join(infix_to_postfix(ep.split(' '))))
分段解释
首先从链表栈中导入栈类,并定义各个操作符的优先级
1 from linked_list_stack import Stack 2 3 SIGN = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 3}
接着定义转换函数,
- 函数接受一个中缀表达式的可迭代对象,创建列表out存放后缀表达式,以及一个空栈s
- 随后开始遍历中缀表达式,判断遍历元素的类型,若为操作数则加入out,
- 若为右括号则依次弹出栈内元素加入out列表,直到遇见左括号,弹出左括号不加入out,
- 若为普通操作符则压入栈中,并对比栈内操作符优先级,依次弹出高优先级或相同优先级的操作符,
- 遍历结束后依次弹出栈内元素,最后返回后缀表达式的字符串形式。
1 def infix_to_postfix(expr): 2 global SIGN 3 out = [] 4 s = Stack() 5 for i in expr: 6 if i in SIGN.keys(): 7 # Pop all high level sign except left bracket 8 while s.top(): 9 if SIGN[s.top()] < SIGN[i] or s.top() == '(': 10 break 11 out.append(s.pop()) 12 # Push sign 13 s.push(i) 14 elif i == ')': 15 # Pop all sign until left bracket encountered 16 while s.top() != '(': 17 out.append(s.pop()) 18 # Pop left bracket 19 s.pop() 20 else: 21 # Push number 22 out.append(i) 23 24 while s.top(): 25 out.append(s.pop()) 26 return out 27 28 29 if __name__ == '__main__': 30 ep = 'a + b * c + ( d * e + f ) * g' 31 print(' '.join(infix_to_postfix(ep.split(' '))))
最后可以得到表达式输出结果为
a b c * + d e * f + g * +
后缀表达式的计算过程其实也是后缀转换为中缀的一个过程:
- 首先依次遍历后缀表达式,
- 当元素为操作数时,压入栈中,
- 当元素为操作符时,弹出栈内最顶上的两个元素,进行操作运算,将得到的结果再次压入栈中,
- 直到后缀表达式遍历结束,此时栈内只有唯一的一个元素即最终的运算结果,弹出栈即可
实现的过程十分简单,具体代码如下,其中中缀表达式转后缀表达式的方法为前面定义的方法
完整代码
1 from linked_list_stack import Stack 2 3 SIGN = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 3} 4 5 6 def postfix_calc(expr): 7 global SIGN 8 s = Stack() 9 for i in expr: 10 if i in SIGN.keys(): 11 right = str(s.pop()) 12 left = str(s.pop()) 13 cal = ' '.join((left, i, right)) 14 # cal = ' '.join([str(s.pop()), i, str(s.pop())][::-1]) 15 s.push(eval(cal)) 16 else: 17 s.push(i) 18 return s.pop() 19 20 if __name__ == '__main__': 21 ep = '( ( 2 + 3 ) * 8 + 5 + 3 ) * 6' 22 print(eval(ep)) 23 print(postfix_calc(infix_to_postfix(ep.split(' ')))) 24 25 ep = '3 + ( 2 * 9 ) / 2 * ( 3 + 6 ) * 7' 26 print(eval(ep)) 27 print(postfix_calc(infix_to_postfix(ep.split(' '))))
最后测试直接运算中缀表达式和中缀转后缀后再计算得到的结果,两者结果相同。
288 288 570.0 570.0