代码练习-简单四则运算解析器

155 阅读3分钟

问题描述

小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

解题思路

  1. 理解问题

    • 你需要实现一个计算器,能够解析并计算包含数字、运算符(+-*/)和括号的字符串表达式。
    • 表达式中的数字是0-9的整数,运算符的优先级需要考虑,括号可以改变运算的顺序。
  2. 数据结构的选择

    • :使用栈来处理运算符和操作数。栈可以帮助你处理运算符的优先级和括号的嵌套。
    • 操作数栈:用于存储数字。
    • 运算符栈:用于存储运算符。
  3. 算法步骤

    • 遍历表达式:逐个字符处理表达式。

    • 处理数字:如果当前字符是数字,继续读取后续字符直到遇到非数字字符,然后将完整的数字压入操作数栈。

    • 处理运算符

      • 如果当前字符是运算符,比较其与运算符栈顶元素的优先级。
      • 如果当前运算符的优先级低于或等于栈顶运算符的优先级,先计算栈顶运算符的操作,然后将当前运算符压入栈。
      • 如果当前运算符的优先级高于栈顶运算符的优先级,直接将当前运算符压入栈。
    • 处理括号

      • 遇到左括号时,将其压入运算符栈。
      • 遇到右括号时,计算括号内的表达式,直到遇到左括号。
    • 最终计算:遍历完表达式后,处理栈中剩余的运算符,得到最终结果。

  4. 运算符优先级

    • 定义一个字典来存储运算符的优先级,例如 {'+': 1, '-': 1, '*': 2, '/': 2}
  5. 计算操作

    • 定义一个辅助函数来执行运算,从操作数栈中弹出两个操作数,从运算符栈中弹出一个运算符,进行计算,并将结果压回操作数栈。

完整代码

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函数的解析器。