问题描述
小F面临一个编程挑战:实现一个基本的计算器来计算简单的字符串表达式的值。该字符串表达式有效,并可能包含数字(0-9)、运算符(+,-,*,/)及括号(())。注意,字符串中不包含空格。除法运算应只保留整数结果。请实现一个解析器计算这些表达式的值,且不使用任何内置的eval函数。
代码实现思路
第一次自己写题解,本身水平也有限...还只在写较简单题的阶段,还望海涵
首先,我们需要解析输入的字符串表达式,识别其中的数字、运算符和括号,并按顺序进行计算。这涉及到几个关键步骤:
-
初始化两个栈:
num_stack用于存储数字,op_stack用于存储操作符。 -
遍历表达式字符串,对于每个字符,根据其类型(数字、运算符、括号)进行不同的处理:
- 数字直接压入
num_stack。 - 操作符需要根据其优先级和栈顶操作符的优先级进行处理。
- 左括号直接压入
op_stack。 - 右括号则触发括号内表达式的计算,直到遇到左括号为止。
- 数字直接压入
-
最后处理栈中剩余的操作符,得到最终计算结果。
代码详细说明
以下是代码的详细实现及其解释:
python
def solution(expression):
num_stack = []
op_stack = []
i = 0
while i < len(expression):
char = expression[i]
if char.isdigit():
# 处理数字
num = int(char)
num_stack.append(num)
elif char in "+-*/":
# 处理操作符
while op_stack and should_calculate_before(op_stack[-1], char):
calculate(num_stack, op_stack)
op_stack.append(char)
elif char == '(':
# 处理左括号
op_stack.append(char)
elif char == ')':
# 处理右括号
while op_stack and op_stack[-1] != '(':
calculate(num_stack, op_stack)
op_stack.pop() # 弹出左括号
i += 1
# 处理剩余的操作符
while op_stack:
calculate(num_stack, op_stack)
return num_stack[0]
def should_calculate_before(op1, op2):
# 判断op1是否应该在op2之前计算
# 例如,乘除优先级高于加减
if op1 in "*/" and op2 in "+-":
return True
if op1 in "+-" and op2 in "*/":
return False
return False
def calculate(num_stack, op_stack):
# 从栈中弹出操作数和操作符进行计算
op = op_stack.pop()
num2 = num_stack.pop()
num1 = num_stack.pop()
if op == '+':
result = num1 + num2
elif op == '-':
result = num1 - num2
elif op == '*':
result = num1 * num2
elif op == '/':
result = num1 // num2 # 只保留整数结果
num_stack.append(result)
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)
代码思路与过程
-
初始化和循环处理:
首先,我们初始化两个栈:
num_stack用于存储数字,op_stack用于存储操作符。这两个栈将帮助我们处理计算的优先级和括号嵌套。python
num_stack = [] op_stack = []接下来,我们使用一个
while循环遍历整个表达式字符串。每次循环读取一个字符,并根据该字符的类型(数字、操作符、括号)进行不同的处理。python
i = 0 while i < len(expression): char = expression[i] -
处理数字:
如果当前字符是数字,我们需要将其转换为整数并压入
num_stack。在我们的例子中,每次读取的字符都是单个数字,因此可以直接转换。对于多位数的情况,需要进一步处理,但这里假设每个数字字符都是有效的单个数字。python
if char.isdigit(): num = int(char) num_stack.append(num) -
处理操作符:
如果当前字符是操作符(+、-、*、/),我们需要考虑操作符的优先级。如果当前操作符的优先级低于或等于栈顶操作符的优先级,我们需要先处理栈顶操作符。
python
elif char in "+-*/": while op_stack and should_calculate_before(op_stack[-1], char): calculate(num_stack, op_stack) op_stack.append(char)这里我们使用了一个辅助函数
should_calculate_before(op1, op2)来判断操作符的优先级:python
def should_calculate_before(op1, op2): if op1 in "*/" and op2 in "+-": return True if op1 in "+-" and op2 in "*/": return False return False该函数判断
op1是否应该在op2之前计算,例如,乘除操作符的优先级高于加减操作符。 -
处理括号:
左括号直接压入
op_stack,而右括号则表示一个子表达式的结束,我们需要计算括号内的表达式。为此,我们不断从栈中弹出操作符和操作数进行计算,直到遇到左括号。python
elif char == '(': op_stack.append(char) elif char == ')': while op_stack and op_stack[-1] != '(': calculate(num_stack, op_stack) op_stack.pop() # 弹出左括号 -
处理剩余的操作符:
当整个表达式遍历完后,可能还有一些操作符留在
op_stack中,我们需要逐一处理它们。python
while op_stack: calculate(num_stack, op_stack) -
计算函数:
计算函数
calculate(num_stack, op_stack)从栈中弹出两个操作数和一个操作符进行计算,并将结果压入num_stack。python
def calculate(num_stack, op_stack): op = op_stack.pop() num2 = num_stack.pop() num1 = num_stack.pop() if op == '+': result = num1 + num2 elif op == '-': result = num1 - num2 elif op == '*': result = num1 * num2 elif op == '/': result = num1 // num2 # 只保留整数结果 num_stack.append(result)
总结
通过上述代码,实现了一个基本的计算器,可以解析和计算包含数字、运算符和括号的字符串表达式。我使用了两个栈来处理操作符的优先级和括号嵌套,通过递归地计算表达式的值,通过解析和计算实现了这一功能。希望这个详细的描述能帮助你更好地理解。