栈基本计算器:中缀表达式求值
在计算机科学中,表达式求值是一个基础且重要的概念。中缀表达式(也称为 infix 表达式)是我们最常用的表达式形式,例如 `3 + 4 2`。将中缀表达式转换为计算机可以理解的格式(如后缀表达式或前缀表达式)并求值,是计算器、编译器等程序设计中的常见任务。
本文将围绕栈这一数据结构,探讨如何实现一个基本计算器,用于计算中缀表达式的值。我们将首先介绍栈的基本概念,然后逐步实现中缀表达式的求值过程。
栈的基本概念
栈(Stack)是一种后进先出(Last In First Out, LIFO)的数据结构。它支持两种基本操作:
1. push:将元素添加到栈顶。
2. pop:从栈顶移除元素。
栈的这些特性使得它在处理需要后进先出顺序的场景中非常有用,例如函数调用栈、表达式求值等。
中缀表达式求值的算法
中缀表达式求值的算法通常遵循以下步骤:
1. 创建两个栈:一个用于存储操作数(数字),另一个用于存储操作符(如加、减、乘、除)。
2. 遍历中缀表达式:从左到右扫描每个字符。
3. 处理数字:如果当前字符是数字,则将其添加到操作数栈中。
4. 处理操作符:
- 如果当前字符是操作符,则根据操作符的优先级进行以下操作:
- 如果操作符栈为空或栈顶元素是左括号 `(`,则直接将操作符入栈。
- 否则,比较当前操作符与栈顶操作符的优先级:
- 如果当前操作符优先级高于或等于栈顶操作符,则从操作符栈中弹出操作符,并从操作数栈中弹出两个操作数进行计算,然后将结果压入操作数栈。重复此步骤,直到遇到一个优先级低于当前操作符的操作符或栈为空。
- 将当前操作符压入操作符栈。
5. 处理括号:如果当前字符是左括号 `(`,则将其压入操作符栈。如果当前字符是右括号 `)`,则从操作符栈中弹出操作符并计算,直到遇到左括号。
6. 处理剩余操作符:遍历完成后,如果操作符栈中还有操作符,则依次弹出并计算。
7. 返回结果:操作数栈中的最后一个元素即为表达式的结果。
代码实现
以下是一个使用 Python 实现的中缀表达式求值器的示例代码:
python
class Calculator:
def __init__(self):
self.num_stack = [] 存储操作数
self.op_stack = [] 存储操作符
def precedence(self, op):
if op == '+' or op == '-':
return 1
if op == '' or op == '/':
return 2
return 0
def apply_operator(self, a, b, op):
if op == '+':
return a + b
if op == '-':
return a - b
if op == '':
return a b
if op == '/':
return a / b
def calculate(self, expression):
for char in expression:
if char.isdigit():
self.num_stack.append(int(char))
elif char == '(':
self.op_stack.append(char)
elif char == ')':
while self.op_stack and self.op_stack[-1] != '(':
self.num_stack.append(self.apply_operator(self.num_stack.pop(), self.num_stack.pop(), self.op_stack.pop()))
self.op_stack.pop() 弹出左括号
else:
while (self.op_stack and self.precedence(self.op_stack[-1]) >= self.precedence(char)):
self.num_stack.append(self.apply_operator(self.num_stack.pop(), self.num_stack.pop(), self.op_stack.pop()))
self.op_stack.append(char)
while self.op_stack:
self.num_stack.append(self.apply_operator(self.num_stack.pop(), self.num_stack.pop(), self.op_stack.pop()))
return self.num_stack.pop()
示例
calculator = Calculator()
expression = "3 + 4 2 / ( 1 - 5 ) ^ 2 ^ 3"
result = calculator.calculate(expression)
print(f"The result of the expression '{expression}' is {result}")
总结
本文介绍了如何使用栈实现中缀表达式求值。通过创建两个栈,我们能够有效地处理操作数和操作符,并按照正确的顺序进行计算。这种方法不仅适用于中缀表达式,还可以扩展到其他类型的表达式求值,如后缀和前缀表达式。
在实际应用中,中缀表达式求值器可以用于各种场景,例如科学计算、编程语言解析器等。通过深入理解栈的特性和算法设计,我们可以构建出高效且可靠的计算器程序。
Comments NOTHING