Java二进制表达式树 - 检查表达式中的括号

时间:2012-02-26 13:53:41

标签: java tree expression binary-tree postfix-notation

我编写了这个程序,它将采用中缀符号表达式并从中构建二叉树。现在,实际工作的唯一输入表达式就像2 + 2.我似乎无法弄清楚如何使它处理括号并采用更长的表达式,如((2 + 2)* 3)。对于我的输出,我试图把它变成后缀表示法,并评估表达式。所以现在如果我插入没有括号的2 + 2我的输出是22+并且它评估它所以它打印4。

我需要找到一种方法让它在每个数字和运算符之间用空格打印输出,并让它接受带括号的更长表达式。我现在不知道如何从这里继续。有人可以帮帮我吗?

谢谢!

这是我的代码:

class ExpressionEvaluator<T> {

    ExpressionEvaluator() {
        Scanner reader = new Scanner(System.in);

        System.out.println("Enter your expression: ");
        String expression = reader.nextLine();    // Reads the expression and trims the spaces.
        expression = expression.replaceAll(" ", "");
        ExpressTree<T> tree = new ExpressTree(expression); // Creates a new binary tree.
    }

    public static void main(String[] args) {
        new ExpressionEvaluator();
    }
}


interface Tree<T> {

    // This is the tree interface with its methods.
    public Node<T> getRoot();

    public void setRoot(Node<T> value);
}


class ExpressTree<T> implements Tree<T> {

    private Node<T> _root;
    private String _value, _expression;
    private Node<T> _treeNode;
    private Stack storage1;
    private Stack<String> storage2;

    public ExpressTree(String expression) {
        expressTreeBuilder(expression);        // Calls the expressTreeBuilder method on the expression.
        postfixTraversal(this.getRoot());
        System.out.println("");
        System.out.println(this.storage2.pop());
    }

    public Node<T> getRoot() {        // Gets the root of the tree.
        return _root;
    }

    public void setRoot(Node<T> _treeNode2) {        // Sets the root which will always be an operator.
        this._root = _treeNode2;
    }

    public boolean isDigit(char value) {    // Method to check if a value is a digit or not.
        if (Character.isDigit(value)) {
            return true;
        } else {
            return false;
        }
    }

    public void expressTreeBuilder(String expression) {

        storage1 = new Stack();    // Stores the nodes.
        storage2 = new Stack<String>();        // Stores the value of the nodes.
        _treeNode = new Node();        // Creates a new node
        _value = null;
        String next = "";

        for (int i = 0; i < expression.length(); i++) {
            char traverse = expression.charAt(i);
            if (i + 1 < expression.length()) {
                next = Character.toString(expression.charAt(i + 1));
            }

            if (traverse == '+') {        // This checks to see the expression is an addition operator.
                Node<T> pop1, pop2;        // It pops the first 2 values from the stack and stores them
                String value1, value2;    // in pop1 and pop2. Then it uses another stack to add them.
                pop1 = (Node<T>) storage1.pop();
                value1 = storage2.pop();    // Stores the right side value.
                value2 = next;    // Stores the left side value.
                _treeNode = new Node();
                _treeNode.setElement(Character.toString(traverse));
                pop2 = new Node();
                pop2.setElement(next);
                pop1.setParent(_treeNode);
                pop2.setParent(_treeNode);
                _treeNode.setLeftSide(pop1);        // Sets the right side of the subtree.
                _treeNode.setRightSide(pop2);        // Sets the left side of the subtree.
                storage1.push(_treeNode);
                storage1.push(pop2);
                int add = (Integer.parseInt(value2) + Integer.parseInt(value1));
                storage2.push(Integer.toString(add));
                this.setRoot(_treeNode);
                i++;
            } else if (traverse == '-') {        // This checks to see the expression is a subtraction operator.
                Node<T> pop1, pop2;        // It pops the first 2 values from the stack and stores them
                String value1, value2;    // in pop1 and pop2. Then it uses another stack to subtract them.
                pop1 = (Node<T>) storage1.pop();
                value1 = storage2.pop();    // Stores the right side value.
                value2 = next;    // Stores the left side value.
                _treeNode = new Node();
                _treeNode.setElement(Character.toString(traverse));
                pop2 = new Node();
                pop2.setElement(next);
                pop1.setParent(_treeNode);
                pop2.setParent(_treeNode);
                _treeNode.setLeftSide(pop1);        // Sets the right side of the subtree.
                _treeNode.setRightSide(pop2);        // Sets the left side of the subtree.
                storage1.push(_treeNode);
                storage1.push(pop2);
                int subtract = (Integer.parseInt(value2) - Integer.parseInt(value1));
                storage2.push(Integer.toString(subtract));
                this.setRoot(_treeNode);
                i++;
            } else if (traverse == '*') {    // This checks to see the expression is a multiplication operator.
                Node<T> pop1, pop2;    // It pops the first 2 values from the stack and stores them
                String value1, value2;    // in pop1 and pop2. Then it uses another stack to multiply them.
                pop1 = (Node<T>) storage1.pop();
                value1 = storage2.pop();    // Stores the right side value.
                value2 = next;    // Stores the left side value.
                _treeNode = new Node();
                _treeNode.setElement(Character.toString(traverse));
                pop2 = new Node();
                pop2.setElement(next);
                pop1.setParent(_treeNode);
                pop2.setParent(_treeNode);
                _treeNode.setLeftSide(pop1);        // Sets the right side of the subtree.
                _treeNode.setRightSide(pop2);        // Sets the left side of the subtree.
                storage1.push(_treeNode);
                storage1.push(pop2);
                int multiply = (Integer.parseInt(value2) * Integer.parseInt(value1));
                storage2.push(Integer.toString(multiply));
                this.setRoot(_treeNode);
                i++;
            } else if (traverse == '(') {

            } else {
                _treeNode = new Node();
                String digits = "";
                while (i < expression.length() && isDigit(expression.charAt(i))) {
                    digits += expression.charAt(i);    // Checks if the value found at the expression is digit
                    if (digits.length() == 1) {
                        break;
                    }
                    i++;
                }

                _treeNode.setElement(digits);        // If it is it will set the element of the node
                storage1.push(_treeNode);        // The node will be pushed onto the stack.
                storage2.push(digits);            // This node will store it's value.
            }
        }
    }

    public void infixTraversal(Node<T> n) {
        if (n != null) {
            infixTraversal(n.getLeftSide());
            System.out.print(n.element() + "");
            infixTraversal(n.getRightSide());
        }
    }

    public void postfixTraversal(Node<T> n) {
        if (n != null) {
            postfixTraversal(n.getLeftSide());
            postfixTraversal(n.getRightSide());
            System.out.print(n.element());
        }
    }
}


class Node<T> {

    public Node<T> _left, _right, _parent;
    private String _element;

    public Node() {
        this._element = null;
        this._left = null;
        this._right = null;
        this._parent = null;
    }

    public String element() {                    // Gets the value of the node.
        return _element;
    }

    public Node<T> getLeftSide() {                // Gets the left side of the node.
        return _left;
    }

    public Node<T> getRightSide() {                // Gets the right side of the node.
        return _right;
    }

    public Node<T> getParent() {                // Gets the parent of the node.
        return _parent;
    }

    public void setElement(String e) {            // Sets the value of the node.
        _element = e;
    }

    public void setLeftSide(Node<T> n) {        // Sets the left side of the node.
        _left = n;
    }

    public void setRightSide(Node<T> n) {        // Sets the right side of the node.
        _right = n;
    }

    public void setParent(Node<T> n) {            // Sets the parent of the node.
        _parent = n;
    }
}

2 个答案:

答案 0 :(得分:3)

您需要一个合适的算法来将中缀表达式转换为后缀表达式。一旦你在postfix中有了表达式,就可以很容易地构造一个解析树或直接评估表达式。经典算法是Shunting-yard algorithm,在维基百科上有相当详细的解释。

完成后缀算法后,您不再需要担心parathesis或operator优先级。它只是一堆价值观,弹出和推动结果。

答案 1 :(得分:0)

您的问题有几个不同的问题:

1)解析表达式并将其分解为树。你需要一个词法分析器(或标记器),即使是一个简单的,优先级,括号等等。

2)转换/评估你的树。有一些很好的经典算法。

3)打印结果(一旦你完成第二部分,我怀疑这很简单;只需要在正确的位置添加正确的空格和括号)。

我建议阅读一些关于所有这些的现有文章,比如说: