You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expression Tree功能异常求助:计算结果与树打印不符合预期

表达式树程序问题排查与修复

输入表达式(3+10)*(5)时,程序计算结果应为65却输出0,打印树结构显示* 5 ( ,完全不符合预期。以下是问题原因分析及修复方案:

核心错误点

1. 括号处理逻辑完全错误

遇到右括号)时,当前代码错误地将栈顶的右操作数当作运算符弹出,且未丢弃左括号(,导致树结构彻底混乱。正确的栈顺序应为:( → 左操作数 → 运算符 → 右操作数,遇到)时需依次弹出右操作数、运算符、左操作数,最后弹出并丢弃(,再将运算符节点挂载左右子树后压入栈。

2. 多位数存储方式错误

处理多位数时,代码将整数转为(char)(value + '0'),仅对0-9的个位数有效。比如数字10会被转为ASCII码58对应的字符:,虽巧合下计算结果正确,但属于错误实现,无法处理大于9的数字。

3. 树遍历顺序错误

当前打印逻辑采用逆中序遍历(右→根→左),导致输出混乱,无法正确还原表达式结构。

修复方案

1. 修正括号处理逻辑

修改)分支的代码,调整弹出顺序并丢弃左括号:

else if (character == ')') {
    ExpressionNode rightNode = stack.pop();
    ExpressionNode operator = stack.pop();
    ExpressionNode leftNode = stack.pop();
    stack.pop(); // 弹出并丢弃左括号'('
    operator.left = leftNode;
    operator.right = rightNode;
    stack.push(operator);
}

2. 重构节点结构以支持多位数

重新定义ExpressionNode,区分数字节点和运算符节点:

private static class ExpressionNode {
    char op;
    int value;
    boolean isNumber;
    ExpressionNode left;
    ExpressionNode right;

    // 运算符节点构造器
    public ExpressionNode(char op) {
        this.op = op;
        this.isNumber = false;
        this.left = null;
        this.right = null;
    }

    // 数字节点构造器
    public ExpressionNode(int value) {
        this.value = value;
        this.isNumber = true;
        this.left = null;
        this.right = null;
    }
}

同时修改数字入栈逻辑,直接创建数字节点:

else {
    StringBuilder number = new StringBuilder();
    while (i < expression.length() && Character.isDigit(expression.charAt(i))) {
        number.append(expression.charAt(i));
        i++;
    }
    i--;

    int value = Integer.parseInt(number.toString());
    stack.push(new ExpressionNode(value));
}

3. 适配节点结构修改求值方法

更新evaluate方法,根据节点类型处理:

private int evaluate(ExpressionNode node) {
    if (node == null) {
        return 0;
    }

    if (node.isNumber) {
        return node.value;
    }

    int left = evaluate(node.left);
    int right = evaluate(node.right);

    return switch (node.op) {
        case '+' -> left + right;
        case '-' -> left - right;
        case '*' -> left * right;
        case '/' -> left / right;
        default -> 0;
    };
}

4. 修正树打印的遍历顺序

改为中序遍历,并给运算符节点添加括号,还原表达式结构:

private void recursivePrintTree(ExpressionNode node) {
    if (node == null) {
        return;
    }

    if (!node.isNumber) {
        System.out.print("(");
    }

    recursivePrintTree(node.left);
    System.out.print(node.isNumber ? node.value + " " : node.op + " ");
    recursivePrintTree(node.right);

    if (!node.isNumber) {
        System.out.print(") ");
    }
}

完整修复代码

package proyecto.pkg3;

import java.util.Stack;

public class ExpressionTree {
    private ExpressionNode root;

    private static class ExpressionNode {
        char op;
        int value;
        boolean isNumber;
        ExpressionNode left;
        ExpressionNode right;

        public ExpressionNode(char op) {
            this.op = op;
            this.isNumber = false;
            this.left = null;
            this.right = null;
        }

        public ExpressionNode(int value) {
            this.value = value;
            this.isNumber = true;
            this.left = null;
            this.right = null;
        }
    }

    public ExpressionTree() {
        root = null;
    }

    public void buildTree(String expression) {
        Stack<ExpressionNode> stack = new Stack<>();

        for (int i = 0; i < expression.length(); i++) {
            char character = expression.charAt(i);

            if (character == ' ') {
                continue;
            }

            if (character == '(') {
                stack.push(new ExpressionNode(character));
            } else if (character == ')') {
                ExpressionNode rightNode = stack.pop();
                ExpressionNode operator = stack.pop();
                ExpressionNode leftNode = stack.pop();
                stack.pop(); // 弹出左括号
                operator.left = leftNode;
                operator.right = rightNode;
                stack.push(operator);
            } else if (isOperator(character)) {
                stack.push(new ExpressionNode(character));
            } else {
                StringBuilder number = new StringBuilder();
                while (i < expression.length() && Character.isDigit(expression.charAt(i))) {
                    number.append(expression.charAt(i));
                    i++;
                }
                i--;

                int value = Integer.parseInt(number.toString());
                stack.push(new ExpressionNode(value));
            }
        }

        root = stack.isEmpty() ? null : stack.pop();
    }

    private boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '*' || c == '/';
    }

    private int evaluate(ExpressionNode node) {
        if (node == null) {
            return 0;
        }

        if (node.isNumber) {
            return node.value;
        }

        int left = evaluate(node.left);
        int right = evaluate(node.right);

        return switch (node.op) {
            case '+' -> left + right;
            case '-' -> left - right;
            case '*' -> left * right;
            case '/' -> left / right;
            default -> 0;
        };
    }

    public void printTree() {
        recursivePrintTree(root);
    }

    private void recursivePrintTree(ExpressionNode node) {
        if (node == null) {
            return;
        }

        if (!node.isNumber) {
            System.out.print("(");
        }

        recursivePrintTree(node.left);
        System.out.print(node.isNumber ? node.value + " " : node.op + " ");
        recursivePrintTree(node.right);

        if (!node.isNumber) {
            System.out.print(") ");
        }
    }

    public int solve() {
        return evaluate(root);
    }
}

验证结果

输入(3+10)*(5),调用solve()返回65,调用printTree()输出((3 + 10 ) * 5 ) ,完全符合预期。

内容的提问来源于stack exchange,提问作者Alex_Vargas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 02:02:36