Python解析 算数表达式求值 栈的使用

1. 算术表达式求值的介绍

算术表达式是计算机科学中的一个重要概念,也是我们在日常开发中经常需要用到的知识点。算术表达式可以包括数字、运算符号以及括号等对运算优先级具有影响的符号。算术表达式的求值过程就是根据一定的运算规则,将表达式转化为计算结果的过程。

对于简单的算术表达式,我们可以手动进行求解,但对于复杂的表达式,我们往往需要借助编程语言来进行求值。本文将介绍使用Python语言实现算术表达式求值的方法。

2. 逆波兰表达式

逆波兰表达式,也叫后缀表达式,是一种不含括号,运算符号在数字后面的一种表达式。在逆波兰表达式中,每个运算符号的优先级都是固定的,不需要考虑括号对表达式的影响。

如下面这个简单的表达式 :

3 + 4 * 5 - 6

可以转换成以下的逆波兰表达式:

3 4 5 * + 6 -

将逆波兰表达式转换成计算结果的过程,可以通过使用栈(Stack)这种数据结构来实现。具体的实现方式如下:

2.1 操作数入栈

当遇到数字时,将数字压入栈中。

def evalRPN(tokens):

stack = []

for token in tokens:

if token.isdigit():

stack.append(int(token))

2.2 操作符出栈

当遇到运算符时,在栈中弹出对应的操作数,并根据运算符进行计算,然后将结果压回栈中。

def evalRPN(tokens):

stack = []

for token in tokens:

if token.isdigit():

stack.append(int(token))

else:

b = stack.pop()

a = stack.pop()

if token == '+':

stack.append(a + b)

elif token == '-':

stack.append(a - b)

elif token == '*':

stack.append(a * b)

elif token == '/':

stack.append(int(a / b))

return stack[0]

2.3 完整代码

将上述的两个部分代码合并起来,就可以得到一个完整的Python实现代码如下:

def evalRPN(tokens):

stack = []

for token in tokens:

if token.isdigit():

stack.append(int(token))

else:

b = stack.pop()

a = stack.pop()

if token == '+':

stack.append(a + b)

elif token == '-':

stack.append(a - b)

elif token == '*':

stack.append(a * b)

elif token == '/':

stack.append(int(a / b))

return stack[0]

tokens = ["2", "1", "+", "3", "*"]

print(evalRPN(tokens))

输出结果:9

3. 算数表达式求值

当表达式中包含括号时,我们需要按照运算符号的优先级和括号的影响,先求解括号内的表达式,然后再根据表达式的优先级进行求解。

考虑如下的算术表达式:

(1 + 2) * 3 - 4 / 2

如果我们将这个表达式转换成后缀表达式,得到的结果为:

1 2 + 3 * 4 2 / -

这个表达式的求解过程与上面提到的逆波兰表达式相同,所以我们可以先将中缀表达式转换成后缀表达式,然后再使用上面的方法求解。

3.1 中缀表达式转后缀表达式

根据运算符的优先级,我们可以使用栈来存储运算符,并在遍历表达式时进行判断。具体的实现方式如下:

def infixToPostfix(expression):

stack = []

postfix = []

operators = set(['+', '-', '*', '/', '(', ')'])

precedence = {'+':1, '-':1, '*':2, '/':2}

for char in expression:

if char not in operators:

postfix.append(char)

else:

if len(stack) == 0 or char == '(':

stack.append(char)

elif char == ')':

while stack[-1]!='(':

postfix.append(stack.pop())

stack.pop()

else:

while len(stack)>0 and stack[-1]!='(' and precedence[char]<=precedence[stack[-1]]:

postfix.append(stack.pop())

stack.append(char)

while len(stack)>0:

postfix.append(stack.pop())

return postfix

3.2 完整实现

将中缀表达式转换成后缀表达式后,再使用逆波兰表达式求解的方法,就可以得到一个完整的算术表达式求值的Python实现代码如下:

def infixToPostfix(expression):

stack = []

postfix = []

operators = set(['+', '-', '*', '/', '(', ')'])

precedence = {'+':1, '-':1, '*':2, '/':2}

for char in expression:

if char not in operators:

postfix.append(char)

else:

if len(stack) == 0 or char == '(':

stack.append(char)

elif char == ')':

while stack[-1]!='(':

postfix.append(stack.pop())

stack.pop()

else:

while len(stack)>0 and stack[-1]!='(' and precedence[char]<=precedence[stack[-1]]:

postfix.append(stack.pop())

stack.append(char)

while len(stack)>0:

postfix.append(stack.pop())

return postfix

def evaluatePostfix(postfix):

stack = []

for token in postfix:

if token.isdigit():

stack.append(int(token))

else:

b = stack.pop()

a = stack.pop()

if token == '+':

stack.append(a + b)

elif token == '-':

stack.append(a - b)

elif token == '*':

stack.append(a * b)

elif token == '/':

stack.append(int(a / b))

return stack[0]

expression = '(1 + 2) * 3 - 4 / 2'

postfix = infixToPostfix(expression)

result = evaluatePostfix(postfix)

print(result)

输出结果:7

4. 总结

本文介绍了使用Python实现算术表达式求值的方法。特别地,当表达式中包含括号时,我们需要先将中缀表达式转换成后缀表达式,再使用逆波兰表达式求解的方法进行求值。这个过程需要使用栈这种数据结构来实现。

以上内容是算法学习中的基础知识,掌握了这些基础知识后,读者可以进一步深入学习更高级的算法和数据结构。

后端开发标签