В java реализовано дерево выражений следующим образом с использованием стеков (LinkedList), но в нем есть ошибки - PullRequest
0 голосов
/ 09 апреля 2020

Я пытался реализовать дерево выражений с помощью стеков (LinkedList), и у меня возникает следующая ошибка при его компиляции.

Note: ExpressionTree.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
import java.util.LinkedList;

public class ExpressionTree implements ExpressionTreeInterface{
    private ExpressionNode root;
    public ExpressionTree(String expression){
        LinkedList l = new LinkedList();
        String[] s = expression.split(" ");
        int i=0;
        for (String a:s){
            if (a == "0" || a == "1" || a == "2" || a == "3" ||a == "4" ||a == "5" ||
                    a == "6" ||a == "7" ||a == "8" ||a == "9"){
                int b = Integer.parseInt(a);
                ExpressionNode e = new ExpressionNode();
                e.operand(b);
                l.add(e);
            }
            else if (a == "*" || a == "/" || a == "+" || a == "-"){
                ExpressionNode e = new ExpressionNode();
                e.operator(a);
                e.right = (ExpressionNode)l.get(l.size()-1);
                e.left = (ExpressionNode)l.get(l.size()-2);
                l.remove(l.size()-1);
                l.remove(l.size()-2);
                l.add(e);
            }
        }
        root = (ExpressionNode)l.get(0);
    }
    public int eval(){
        return eval(root);
    }
    public int eval(ExpressionNode r){
        if (r.left!=null && r.right!=null){
            if (r.getOperator() == "+"){
                return eval(r.left) + eval(r.right);
            } else if (r.operator == "*"){
                return eval(r.left) * eval(r.right);
            } else if (r.operator == "/"){
                return eval(r.left) / eval(r.right);
            } else {
                return eval(r.left) - eval(r.right);
            }
        } else {
            return r.getOperand();
            }

        }
    private static class ExpressionNode{
        int operand;
        String operator;
        ExpressionNode left;
        ExpressionNode right;
        public void operator(String operator){
            this.operator = operator;
        }
        public void operand(int operand){
            this.operand = operand;
        }
        public String getOperator(){
            return operator;
        }
        public int getOperand(){
            return operand;
        }
    }
    public String postfix(){
        return postfix(root).trim();
    }
    private String postfix(ExpressionNode s){
        if (s.left == null && s.right == null){
            return Integer.toString(s.getOperand());
        } else{
            return postfix(s.left) + " " + postfix(s.right) + " " + s.getOperator();
        }
    }
    public String prefix(){
        return prefix(root).trim();
    }
    private String prefix(ExpressionNode s){
        if (s.left == null && s.right == null){
            return Integer.toString(s.getOperand());
        } else{
            return s.getOperator() + " " + prefix(s.left) + " " + prefix(s.right);
        }
    }
    public String infix(){
        return infix(root).trim();
    }
    private String infix(ExpressionNode s){
        if (s.left == null && s.right == null){
            return Integer.toString(s.getOperand());
        } else{
            return infix(s.left) + " " + s.getOperator() + " " + infix(s.right);
        }  
    }
}

Кроме того, я создал следующий тестовый класс, но он снова имеет следующую ошибку.

at java.util.LinkedList.checkElementIndex(LinkedList.java:555)
at java.util.LinkedList.get(LinkedList.java:476)
at ExpressionTree.<init>(ExpressionTree.java:27)
at Testfile.main(Testfile.java:4)
public class Testfile {
    public static void main(String[] args){
        String a = "34 2 - 5 *";
        ExpressionTree s = new ExpressionTree(a);
        System.out.println(s.eval());
    }
}

Где я сделал не так? Я думаю, что использовал много рекурсии, так что, возможно, там произошла ошибка, но я не могу понять, где.

1 Ответ

1 голос
/ 09 апреля 2020

В вашем коде есть несколько проблем:

Первая проблема - Вы не можете сравнить строку в java, используя операторы ==, которые вам нужны, и можете использовать такую ​​функцию, как .equals () сравнить два строковых значения. Таким образом, код этого кода:

if (a == "0" || a == "1" || a == "2" || a == "3" ||a == "4" ||a == "5" ||
                a == "6" ||a == "7" ||a == "8" ||a == "9")

изменяется на:

 if (a.equals("0")|| a.equals("1") ||a.equals("2") || a.equals("3") ||a.equals("4") ||a.equals("5") ||
                    a.equals("6") ||a.equals("7") ||a.equals("8") ||a.equals("9"))

То же самое относится и к этой части фрагмента кода:

else if (a == "*" || a == "/" || a == "+" || a == "-")

, которую необходимо использовать В этом тоже есть функция .equals.

Та же проблема есть и в функции eval в этой части:

if (r.left!=null && r.right!=null){
        if (r.getOperator() == "+"){
            return eval(r.left) + eval(r.right);
        } else if (r.operator == "*"){
            return eval(r.left) * eval(r.right);
        } else if (r.operator == "/"){
            return eval(r.left) / eval(r.right);
        } else {
            return eval(r.left) - eval(r.right);
        }
    } else {
        return r.getOperand();
        }

Вторая проблема - на входе expression string ("34 2 - 5 *") одна из строк 34, но она не будет удовлетворять этому условию:

  if (a == "0" || a == "1" || a == "2" || a == "3" ||a == "4" ||a == "5" ||
                    a == "6" ||a == "7" ||a == "8" ||a == "9")

Таким образом, вместо проверки, является ли ваша строка номером или нет как вы можете создать вспомогательную функцию, чтобы сделать то же самое, как это, и вызвать то же самое:

 private boolean checkStringIsNumber(String s) {
    boolean numeric = true;

    try {
        Integer num = Integer.parseInt(s);
    } catch (NumberFormatException e) {
        numeric = false;
    }
    return numeric;
}

Третья проблема - в этих двух строках:

 l.remove(l.size()-1);
 l.remove(l.size()-2);

Предположим, Ваш список ссылок имеет два узла на данный момент. После l1, l2. После выполнения первого оператора

l.remove(l.size()-1);

обновленный список ссылок будет содержать один узел, т.е. l1. Теперь, если вы выполните эту инструкцию

 l.remove(l.size()-2);

Она выдаст исключение, поскольку размер списка ссылок теперь равен 1, а l.size () - 2 вернется в -1, что является недопустимым индексом;

Итак, я полагаю, что вы хотите удалить последние 2 узла, чтобы вы могли сделать вместо этих двух операторов следующее:

 l.remove(l.size()-1);
 l.remove(l.size()-1);

Итак, после решения всех этих проблем обновил код конструктора ExpressionTree is:

 public ExpressionTree(String expression){
        LinkedList l = new LinkedList();
        String[] s = expression.split(" ");
        int i=0;
        for (String a:s){
            if (checkStringIsNumber(a)){
                int b = Integer.parseInt(a);
                ExpressionNode e = new ExpressionNode();
                e.operand(b);
                l.add(e);
            }
            else if (a.equals("*") || a.equals("/") || a.equals("+") || a.equals("-")){
                ExpressionNode e = new ExpressionNode();
                e.operator(a);
                e.right = (ExpressionNode)l.get(l.size()-1);
                e.left = (ExpressionNode)l.get(l.size()-2);
                l.remove(l.size()-1);
                l.remove(l.size()-1);
                l.add(e);
            }
        }
        root = (ExpressionNode)l.get(0);
    }

и обновленный код функции eval is:

 public int eval(ExpressionNode r){
    if (r.left!=null && r.right!=null){
        if (r.getOperator().equals("+")){
            return eval(r.left) + eval(r.right);
        } else if (r.operator.equals("*")){
            return eval(r.left) * eval(r.right);
        } else if (r.operator.equals("/")){
            return eval(r.left) / eval(r.right);
        } else {
            return eval(r.left) - eval(r.right);
        }
    } else {
        return r.getOperand();
        }

}

После внесения этих изменений вышеприведенное выражение отлично работает и выдает результат как 160.

...