数据结构-栈-表达式运算

文章详细描述了如何使用栈数据结构实现整数表达式的计算,包括中缀表达式转后缀表达式的过程以及具体步骤,涉及符号优先级判断和运算符的执行逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

表达式运算实现:

1.栈实现

public class ExpressCalc {

    public static void main(String[] args) {
        /*
        使用栈实现一个0-9整数带括号的表达式计算
        处理步骤:
        1.创建两个栈,一个符号栈(左括号、右括号、加、减、乘、除),左括号优先级最高,右括号优先级最低,一个数字栈(0-9)
        2.遇到数字:直接入数字栈
        3.遇到符号:
            如果符号栈为空,则直接入符号栈
            如果当前符号优先级 > 栈顶符号优先级:直接入符号栈
            如果当前符号优先级 <= 栈顶符号优先级:将数字栈与符号栈元素弹出,进行运算,直到栈为空或者当前符号优先级 > 栈顶符号优先级为止
        */
        String[] expressArray = {
            "2+3*(1+2*4)-3*5",
            "2+3",
            "2+3+(3*4/2)-1",
            "2+3+(3*4/2+5)-1",
            "2+3+(3*4/2+5-9)-1",
            "2+3+(3*4/2+5-9)-1+2*(1+2)",
            "2",
        };

        for (String expressStr : expressArray) {
            int num = calcExpress(expressStr);
            System.out.println(expressStr + "=" + num);
        }
    }

    private static int calcExpress(String expressStr) {

        Stack<Integer> numSt = new Stack<>();
        Stack<Character> symbolSt = new Stack<>();

        char[] cs = expressStr.toCharArray();
        for (int i = 0; i < cs.length; i++) {
            // 匹配数字
            if(String.valueOf(cs[i]).matches("\\d")){
                numSt.add(cs[i] - '0');
            }else if(cs[i] == '+' || cs[i] == '-' || cs[i] == '*' || cs[i] == '/' || cs[i] == '(' || cs[i] == ')'){
                if(symbolSt.isEmpty() || priority(cs[i], symbolSt.peek())){
                    symbolSt.add(cs[i]);
                }else{
                    while(!symbolSt.isEmpty() && symbolSt.peek() != '(' && !priority(cs[i], symbolSt.peek())){
                        Integer n1 = numSt.pop();
                        Integer n2 = numSt.pop();
                        int res = calc(n2, n1, symbolSt.pop());
                        numSt.add(res);
                    }
                    if(!symbolSt.isEmpty() && symbolSt.peek() == '(') symbolSt.pop();
                    if(cs[i] != ')') symbolSt.add(cs[i]);
                }
            }
        }

        while(!symbolSt.isEmpty()){
            Integer n1 = numSt.pop();
            Integer n2 = numSt.pop();
            int res = calc(n2, n1, symbolSt.pop());
            numSt.add(res);
        }
        return numSt.pop();
    }

    // 优先级判断 a > b : 返回true,否则返回false
    public static boolean priority(char a, char b){
        if(a == '(') return true;
        if((a == '*' || a == '/') && (b == '+' || b == '-' || b == ')')) return true;
        if((a == '+' || a == '-') && b == ')') return true;
        return false;
    }

    public static int calc(int a, int b, char express){
        switch (express){
            case '+':
                return a + b;
            case '-':
                return a - b;
            case '*':
                return a * b;
            case '/':
                return a / b;
            default:
                throw new RuntimeException("不支持" + express + "进行运算");
        }
    }
}

2.中缀表达式转后缀表达式计算

https://blog.youkuaiyun.com/Linging_24/article/details/104481492

### 在算术表达式求值中的应用 是一种遵循后进先出(LIFO, Last In First Out)原则的数据结构,在处理中缀算术表达式的求值过程中具有重要作用。通过维护两个——操作数(OPND)和运算(OPTR),可以有效地解析并计算复杂的算术表达式。 #### 初始化阶段 在开始计算之前,需要完成以下初始化工作: - 将 **OPND** 设置为空。 - 在 **OPTR** 中压入初始符号 `'#'` 表示表达式的起点[^2]。 #### 处理流程 对于输入的每一个字符,按照其性质分别进行如下处理: 1. 如果当前字符是一个数字,则将其转换为数值形式,并压入到 **OPND** 中。 2. 如果当前字符是运算符,则需与 **OPTR** 顶的运算符比较优先级: - 当前运算符的优先级较高时,直接将该运算符压入 **OPTR** - 当前运算符的优先级较低或相等时,从 **OPTR** 弹出一个运算符以及从 **OPND** 弹出两个操作数,执行相应运算并将结果重新压回 **OPND** - 特殊情况下,如果遇到匹配的右括号 `')'`,则应持续弹出 **OPTR** 直到找到对应的左括号 `'('` 并丢弃之。 3. 继续上述逻辑直至整个表达式被完全扫描完毕。 4. 最终当所有字符都已处理完成后,可能还存在部分未解决的操作留在内,此时只需不断取出剩余的运算符及其对应的操作数继续完成最后几步计算即可。 最终得到的结果即存储于 **OPND** 顶部位置处。 ```python def precedence(op): """定义运算符优先级""" if op in ('+', '-'): return 1 elif op in ('*', '/'): return 2 elif op == '#': return 0 else: raise ValueError(f"未知运算符 {op}") def apply_operator(operand_stack, operator): """根据指定运算符对操作数堆执行一次二元运算""" b = operand_stack.pop() a = operand_stack.pop() if operator == '+': result = a + b elif operator == '-': result = a - b elif operator == '*': result = a * b elif operator == '/': if b != 0: result = a / b else: raise ZeroDivisionError("除零错误") operand_stack.append(result) def evaluate_expression(expression): """评估给定字符串表示的中缀表达式""" OPND = [] # 操作数 OPTR = ['#'] # 运算 i = 0 while True: token = expression[i] if '0' <= token <= '9': # 数字情况 num_str = '' while i < len(expression) and ('0' <= expression[i] <= '9'): num_str += expression[i] i += 1 OPND.append(int(num_str)) continue elif token in "+-*/()": # 符号情况 top_optr = OPTR[-1] if (precedence(top_optr) < precedence(token)) or (token == '('): OPTR.append(token) elif ((top_optr not in "()") and (precedence(top_optr) >= precedence(token))): popped_optr = OPTR.pop() apply_operator(OPND, popped_optr) i -= 1 elif token == ')': while OPTR[-1] != '(': popped_optr = OPTR.pop() apply_operator(OPND, popped_optr) OPTR.pop() # 移除左括号 elif token == '#': break # 结束标志 i += 1 while len(OPTR) > 1: apply_operator(OPND, OPTR.pop()) return OPND[0] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值