Python与数据结构[1] -> 栈/Stack[1] -> 中缀表达式与后缀表达式的转换和计算

中缀表达式与后缀表达式的转换和计算


目录

  1. 中缀表达式转换为后缀表达式
  2. 后缀表达式的计算

 

1 中缀表达式转换为后缀表达式

中缀表达式转换为后缀表达式的实现方式为:

  1. 依次获取中缀表达式的元素,
  2. 若元素为操作数(数字/字母等),则加入后缀表达式中
  3. 若元素为操作符,则压入栈中,此时对比入栈操作符与栈内元素的计算等级,等级大于或等于入栈元素的栈内操作符都将被弹出栈,加入到后缀表达式中
  4. 左括号直接入栈,优先级最高,不弹出栈内元素
  5. 右括号不入栈,而是弹出所有元素加入后缀表达式,直至遇见匹配的左括号,并弹出左括号但不加入后缀表达式中
  6. 当中缀表达式的元素耗尽后,依次弹出栈内元素加入到后缀表达式中。

代码实现过程如下,

完整代码

 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(' '))))
View Code

分段解释

首先从链表栈中导入栈类,并定义各个操作符的优先级

1 from linked_list_stack import Stack
2 
3 SIGN = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 3}

接着定义转换函数,

  1. 函数接受一个中缀表达式的可迭代对象,创建列表out存放后缀表达式,以及一个空栈s
  2. 随后开始遍历中缀表达式,判断遍历元素的类型,若为操作数则加入out,
  3. 若为右括号则依次弹出栈内元素加入out列表,直到遇见左括号,弹出左括号不加入out,
  4. 若为普通操作符则压入栈中,并对比栈内操作符优先级,依次弹出高优先级或相同优先级的操作符,
  5. 遍历结束后依次弹出栈内元素,最后返回后缀表达式的字符串形式。
 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 * +

 

2 后缀表达式的计算

 

后缀表达式的计算过程其实也是后缀转换为中缀的一个过程:

  1. 首先依次遍历后缀表达式,
  2. 当元素为操作数时,压入栈中,
  3. 当元素为操作符时,弹出栈内最顶上的两个元素,进行操作运算,将得到的结果再次压入栈中,
  4. 直到后缀表达式遍历结束,此时栈内只有唯一的一个元素即最终的运算结果,弹出栈即可

实现的过程十分简单,具体代码如下,其中中缀表达式转后缀表达式的方法为前面定义的方法

完整代码

 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

 

posted @ 2018-01-14 22:13  StackLike  阅读(936)  评论(0编辑  收藏  举报