问题描述
小F面临一个编程挑战:实现一个基本的计算器来计算简单的字符串表达式的值。该字符串表达式有效,并可能包含数字(0-9)、运算符+、-及括号()。注意,字符串中不包含空格。除法运算应只保留整数结果。请实现一个解析器计算这些表达式的值,且不使用任何内置的eval函数。
测试样例
样例1:
输入:
expression = "1+1"
输出:2
样例2:
输入:
expression = "3+4*5/(3+2)"
输出:7
思路
我们的目标是解析并计算一个包含数字、加减乘除运算符以及括号的字符串表达式。为了实现这一点,我们需要处理以下几个关键点:
1. 数据结构选择
我们使用两个栈来帮助解析和计算表达式:
- 数值栈 (
values) :用于存储中间计算结果和最终结果。 - 运算符栈 (
operators) :用于存储待处理的运算符。
2. 处理数字
当我们遇到数字时,需要将其完整地读取出来并转换为整数,然后压入数值栈。这是因为数字可能不止一位,例如 "123" 应该被解析为一个整体的数字 123。
3. 处理运算符
运算符的处理需要考虑优先级。我们使用一个辅助函数 greater_precedence 来比较运算符的优先级:
- 如果当前运算符的优先级高于或等于栈顶运算符的优先级,我们先计算栈顶的运算符。
- 否则,我们将当前运算符压入运算符栈。
4. 处理括号
括号用于改变运算的优先级:
- 当遇到左括号
(时,直接将其压入运算符栈。 - 当遇到右括号
)时,不断弹出运算符栈中的运算符并计算,直到遇到左括号(,然后将左括号从栈中弹出。
5. 计算结果
- 遍历完表达式后,可能还会剩下一些运算符在栈中,继续计算直到运算符栈为空。
- 最终,数值栈中应该只剩下一个值,即表达式的计算结果。
具体实现
下面是详细的实现步骤和代码:
辅助函数
- apply_operator:执行运算符对应的数学运算,并将结果存回数值栈中。
- greater_precedence:比较运算符的优先级。
def apply_operator(operators, values):
operator = operators.pop()
right = values.pop()
left = values.pop()
if operator == '+':
values.append(left + right)
elif operator == '-':
values.append(left - right)
elif operator == '*':
values.append(left * right)
elif operator == '/':
values.append(int(left / right)) # 整数除法
def greater_precedence(op1, op2):
precedence = {'+': 1, '-': 1, '*': 2, '/': 2}
return precedence[op1] >= precedence[op2]
主函数
-
初始化两个栈:数值栈
values和运算符栈operators。 -
遍历表达式中的每个字符:
- 如果是数字,读取完整数字并压入数值栈。
- 如果是左括号
(,压入运算符栈。 - 如果是右括号
),计算直到遇到左括号(。 - 如果是运算符,根据优先级决定是否先计算栈顶的运算符,然后将当前运算符压入运算符栈。
-
遍历完表达式后,继续计算剩余的运算符。
-
返回数值栈中唯一的值作为结果。
def solution(expression):
operators = []
values = []
i = 0
while i < len(expression):
if expression[i].isdigit():
val = 0
while i < len(expression) and expression[i].isdigit():
val = val * 10 + int(expression[i])
i += 1
values.append(val)
continue
if expression[i] == '(':
operators.append(expression[i])
elif expression[i] == ')':
while operators[-1] != '(':
apply_operator(operators, values)
operators.pop() # 弹出 '('
else:
while operators and operators[-1] != '(' and greater_precedence(operators[-1], expression[i]):
apply_operator(operators, values)
operators.append(expression[i])
i += 1
while operators:
apply_operator(operators, values)
return values[0]