2015-05-03 83 views
7

我應該實現一個包含數學表達式的二叉樹,對每個二元或一元表達式使用不同的類。例如: :數學表達式二叉樹

Expression e = new Sin(
        new Pow(
         new Mul(
          new Plus(
           new Mul(new Num(2), new Var("x")), 
           new Var("y")), 
          new Num(4)), 
        new Var("x"))); 

樹的葉子可以是變量或數字。每個變量可以轉換爲另一個表達式與方法:

Expression assign(String var, Expression expression) 

我有2個抽象類的一元和二元運算符。

我一直遇到困難,弄清楚如何將相同的表達式賦值給表達式本身的變量之一。例如:

Expression e1 = new Plus(1,"x"); 
e1.assign("x", e1); 
System.out.println(e1.toString()); 

輸出應該是:

((x+1)+1) 

什麼實際發生的是,表達式的左側部分本身指向這會導致一個無限循環。有沒有辦法使對象重複,但用不同的指針來避免它?或者,也許採用不同的方式來實現「分配」方法的工作方式?

這是我實現:

BinaryExpression類:

import java.util.List; 
import java.util.Map; 


abstract public class BinaryExpression extends BaseExpression implements Expression { 

    protected Expression first, second; 

    public BinaryExpression(Expression first, Expression second) { 
     this.setSecond(second); 
     this.setFirst(first); 
    } 
    public BinaryExpression(double number1, double number2) { 
     this(new Num(number1), new Num(number2)); 
    } 
    public BinaryExpression(double number, String variable) { 
     this(new Num(number), new Var(variable)); 
    } 
    public BinaryExpression(String variable, double number) { 
     this(new Var(variable), new Num(number)); 
    } 
    public BinaryExpression(String variable1, String variable2) { 
     this(new Var(variable1), new Var(variable2)); 
    } 
    public BinaryExpression(Expression expression, String variable) { 
     this(expression , new Var(variable)); 
    } 
    public BinaryExpression(double number, Expression expression) { 
     this(new Num(number), expression); 
    } 
    public BinaryExpression(Expression expression, double number) { 
     this(expression, new Num(number)); 
    } 
    public BinaryExpression(String variable, Expression expression) { 
     this(new Var(variable), expression); 
    } 

    public Expression getSecond() { 
     return second; 
    } 

    public void setSecond(Expression second) { 
     this.second = second; 
    } 

    public Expression getFirst() { 
     return first; 
    } 

    public void setFirst(Expression first) { 
     this.first = first; 
    } 
    public double evaluate(Map<String, Double> assignment) throws Exception { 
     try { 
      return operate(first.evaluate(assignment), second.evaluate(assignment)); 
     } catch (Exception e) { 
      throw new Exception(e.getMessage()); 
     } 
    } 
    abstract public double operate(double first, double second) throws Exception; 

    public List<String> getVariables() { 
     java.util.List<String> firstList, secondList; 
     firstList = this.first.getVariables(); 
     secondList = this.second.getVariables(); 
     for (int i = 0; i < secondList.size(); i++) { 
      boolean seen = false; 
      for (int j = 0; j < firstList.size(); j++) { 
       if (((String) firstList.get(j)).equals((String) secondList.get(i))) { 
        seen = true; 
        break; 
       } 
      } 
      if (!seen) { 
       firstList.add(secondList.get(i)); 
      } 
     } 
     return firstList; 
    } 

    public Expression assign(String var, Expression expression) { 
     this.first = first.assign(var, expression); 
     this.second = second.assign(var, expression); 
     return this; 
    } 

    abstract public String operator(); 

    public String toString() { 
     return "(" + this.first.toString() + 
       this.operator() + 
       this.second.toString() + ")"; 
    } 
} 

變量類:

import java.util.ArrayList; 
import java.util.List; 
import java.util.Map; 


public class Var implements Expression { 
    private String variable; 
    /** 
    * setting the desired variable. 
    * @param variable the variable to set 
    */ 
    public Var(String variable) { 
     this.variable = variable; 
    } 
    /** 
    * getting the variable string. 
    * @return the variable string 
    */ 
    public String getVariable() { 
     return variable; 
    } 
    /** 
    * setting the variable string. 
    * @param newVariable the string we want to set. 
    */ 
    public void setVariable(String newVariable) { 
     this.variable = newVariable; 
    } 
    @Override 
    public double evaluate(Map<String, Double> assignment) throws Exception { 
     if (assignment.containsKey(this.variable)) { 
      return assignment.get(this.variable); 
     } else { 
      throw new Exception("variable wasn't assigned"); 
     } 
    } 
    @Override 
    public double evaluate() throws Exception { 
     throw new Exception("variable wasn't assigned"); 
    } 
    @Override 
    public List<String> getVariables() { 
     java.util.List<String> singleVariable = new ArrayList<String>(); 
     singleVariable.add(this.variable); 
     return singleVariable; 
    } 
    @Override 
    public Expression assign(String var, Expression expression) { 
     if (var.equals(this.variable)) { 
      return expression; 
     } else { 
      return this; 
     } 
    } 
    public String toString() { 
     return this.variable; 
    } 
} 

Number類:

import java.util.ArrayList; 
import java.util.List; 
import java.util.Map; 


public class Num implements Expression { 
    private double value; 
    /** 
    * creating a new number. 
    * @param number the value to set. 
    */ 
    public Num(double number) { 
     this.setValue(number); 
    } 
    /** 
    * getting the number's value. 
    * @return the value to set. 
    */ 
    public double getValue() { 
     return value; 
    } 
    /** 
    * setting a new number. 
    * @param newValue the number to set. 
    */ 
    public void setValue(double newValue) { 
     this.value = newValue; 
    } 
    @Override 
    public double evaluate(Map<String, Double> assignment) { 
     return getValue(); 
    } 
    @Override 
    public double evaluate() { 
     return getValue(); 
    } 
    @Override 
    public List<String> getVariables() { 
     java.util.List<String> emptyList = new ArrayList<String>(); 
     return emptyList; 
    } 
    @Override 
    public Expression assign(String var, Expression expression) { 
     return this; 
    } 
    public String toString() { 
     return Double.toString(this.value); 
    } 
} 

任何形式的幫助是apprec iated。

我在這裏將我得到的錯誤:

Exception in thread "main" java.lang.StackOverflowError 
    at sun.misc.FloatingDecimal$BinaryToASCIIBuffer.dtoa(Unknown Source) 
    at sun.misc.FloatingDecimal$BinaryToASCIIBuffer.access$100(Unknown Source) 
    at sun.misc.FloatingDecimal.getBinaryToASCIIConverter(Unknown Source) 
    at sun.misc.FloatingDecimal.getBinaryToASCIIConverter(Unknown Source) 
    at sun.misc.FloatingDecimal.toJavaFormatString(Unknown Source) 
    at java.lang.Double.toString(Unknown Source) 
    at Num.toString(Num.java:50) 
    at BinaryExpression.toString(BinaryExpression.java:94) 
    at BinaryExpression.toString(BinaryExpression.java:94) 
    at BinaryExpression.toString(BinaryExpression.java:96) 
    at BinaryExpression.toString(BinaryExpression.java:94) 
    at BinaryExpression.toString(BinaryExpression.java:96) 
    at BinaryExpression.toString(BinaryExpression.java:94) 
    at BinaryExpression.toString(BinaryExpression.java:96) 
    at BinaryExpression.toString(BinaryExpression.java:94) 
    at BinaryExpression.toString(BinaryExpression.java:96) 
    at BinaryExpression.toString(BinaryExpression.java:94) 
    at BinaryExpression.toString(BinaryExpression.java:96) 
    at BinaryExpression.toString(BinaryExpression.java:94) 
    at BinaryExpression.toString(BinaryExpression.java:96)... 

這裏還是要在加類的clone方法的例子:

public Expression clone() { 
    Expression newFirst = this.first, newSecond = this.second; 
    return new Plus(newFirst, newSecond); 
} 

我試圖通過改變使用它分配的無功方法是這樣的:

public Expression assign(String var, Expression expression) { 
    if (var.equals(this.variable)) { 
     return expression.clone(); 
    } else { 
     return this; 
    } 
} 

此外我還試圖通過改變分配甲基修復它OD這種方式改變VAR方法之後並沒有使用其他的功能的工作:

public Expression assignHelp(String var, Expression expression) { 
    this.first = first.assignHelp(var, expression); 
    this.second = second.assignHelp(var, expression); 
    return this; 
} 
public Expression assign(String var, Expression expression) { 
    return assignHelp(var, expression.clone()); 
} 
+0

爲什麼你需要一個賦值方法而不只是建立一個新的表達方式? – fdsa

+0

如果Expression實現Clonable,則可以調用expression.clone()。 –

+0

我試圖通過這種方式爲每個類的克隆方法: 表達式克隆(){ 返回新的表達式(this.first,this.second); } 並在var類reurning expression.clone()中的assign方法,但它不工作,我不知道爲什麼。 – Ryan

回答

1

(從評論)

有表達實現可克隆,並調用expression.clone()。

的clone()應該克隆內部元件太(深拷貝)

因此,克隆看起來像

public Expression clone() { 
    return new Plus(this.first.clone(), this.second.clone()); 
}