问题描述
小F面临一个编程挑战:实现一个基本的计算器来计算简单的字符串表达式的值。该字符串表达式有效,并可能包含数字(0-9)、运算符+、-及括号()。注意,字符串中不包含空格。除法运算应只保留整数结果。请实现一个解析器计算这些表达式的值,且不使用任何内置的eval函数。
测试样例
样例1:
输入:
expression = "1+1"
输出:2
样例2:
输入:
expression = "3+4*5/(3+2)"
输出:7
样例3:
输入:
expression = "4+2*5-2/1"
输出:12
样例4:
输入:
expression = "(1+(4+5+2)-3)+(6+8)"
输出:23
样例5:
输入:
expression = "2*(5+5*2)/3+(6+8*3)"
输出:40
解题思路
-
理解问题:
- 你需要实现一个计算器,能够解析并计算包含数字、运算符(
+、-、*、/)和括号的字符串表达式。 - 表达式中的数字是0-9的整数,运算符的优先级需要考虑,括号可以改变运算的顺序。
- 你需要实现一个计算器,能够解析并计算包含数字、运算符(
-
数据结构的选择:
- 栈:使用栈来处理运算符和操作数。栈可以帮助你处理运算符的优先级和括号的嵌套。
- 操作数栈:用于存储数字。
- 运算符栈:用于存储运算符。
-
算法步骤:
-
遍历表达式:逐个字符处理表达式。
-
处理数字:如果当前字符是数字,继续读取后续字符直到遇到非数字字符,然后将完整的数字压入操作数栈。
-
处理运算符:
- 如果当前字符是运算符,比较其与运算符栈顶元素的优先级。
- 如果当前运算符的优先级低于或等于栈顶运算符的优先级,先计算栈顶运算符的操作,然后将当前运算符压入栈。
- 如果当前运算符的优先级高于栈顶运算符的优先级,直接将当前运算符压入栈。
-
处理括号:
- 遇到左括号时,将其压入运算符栈。
- 遇到右括号时,计算括号内的表达式,直到遇到左括号。
-
最终计算:遍历完表达式后,处理栈中剩余的运算符,得到最终结果。
-
-
运算符优先级:
- 定义一个字典来存储运算符的优先级,例如
{'+': 1, '-': 1, '*': 2, '/': 2}。
- 定义一个字典来存储运算符的优先级,例如
-
计算操作:
- 定义一个辅助函数来执行运算,从操作数栈中弹出两个操作数,从运算符栈中弹出一个运算符,进行计算,并将结果压回操作数栈。
完整代码
def solution(expression):
precedence = {'+': 1, '-': 1, '*': 2, '/': 2}
operand_stack = []
operator_stack = []
def apply_operator():
operator = operator_stack.pop()
b = operand_stack.pop()
a = operand_stack.pop()
if operator == '+':
operand_stack.append(a + b)
elif operator == '-':
operand_stack.append(a - b)
elif operator == '*':
operand_stack.append(a * b)
elif operator == '/':
operand_stack.append(a // b)
i = 0
while i < len(expression):
char = expression[i]
if char.isdigit():
num = 0
while i < len(expression) and expression[i].isdigit():
num = num * 10 + int(expression[i])
i += 1
operand_stack.append(num)
continue
if char in precedence:
while (operator_stack and operator_stack[-1] != '(' and
precedence[operator_stack[-1]] >= precedence[char]):
apply_operator()
operator_stack.append(char)
elif char == '(':
operator_stack.append(char)
elif char == ')':
while operator_stack and operator_stack[-1] != '(':
apply_operator()
operator_stack.pop()
i += 1
while operator_stack:
apply_operator()
return operand_stack[0]
if __name__ == "__main__":
# You can add more test cases here
print(solution("1+1") == 2)
print(solution("3+4*5/(3+2)") == 7)
print(solution("4+2*5-2/1") == 12)
print(solution("(1+(4+5+2)-3)+(6+8)") == 23)
学习总结
在这次编程训练中,我深入学习了如何使用栈数据结构来解析和计算包含数字、加减乘除运算符及括号的字符串表达式,同时确保除法运算只保留整数结果。通过逐个字符扫描表达式,并根据当前字符类型执行相应操作,我设计并实现了一个不使用内置eval函数的解析器。