数据结构与算法之 leetcode 栈基本计算器 中缀表达式求值

数据结构与算法阿木 发布于 5 天前 2 次阅读


栈基本计算器:中缀表达式求值

在计算机科学中,表达式求值是一个基础且重要的概念。中缀表达式(也称为 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}")


总结

本文介绍了如何使用栈实现中缀表达式求值。通过创建两个栈,我们能够有效地处理操作数和操作符,并按照正确的顺序进行计算。这种方法不仅适用于中缀表达式,还可以扩展到其他类型的表达式求值,如后缀和前缀表达式。

在实际应用中,中缀表达式求值器可以用于各种场景,例如科学计算、编程语言解析器等。通过深入理解栈的特性和算法设计,我们可以构建出高效且可靠的计算器程序。