我有一個List<TermNode>
其中包含操作的所有操作數,如+
或*
。也就是說,它不是一個二叉樹結構,而是一個樹,其中每個節點可能包含多個子節點。 A TermNode
可以是變量,運算符,函數或數字。一個數字和一個變量節點包含一個空的兒童列表(將孩子視爲一個操作的參數)。列表分組由對象字段和計數的發生
public class TermNode {
/**
* The value this {@link TermNode} holds.
*/
private String value;
/**
* The arguments of this {@link TermNode}.
*
* This {@link List} is empty if the {@link TermTypeEnum} of this {@link TermNode}
* is either {@link TermTypeEnum}.NUMBER or {@link TermTypeEnum}.VARIABLE.
*/
private List<TermNode> children;
/**
* The {@link TermTypeEnum} of this {@link TermNode}.
*/
private TermTypeEnum type;
public TermNode(ComplexNumber number) {
this(number.toString(), new ArrayList<TermNode>(), TermTypeEnum.NUMBER);
}
public TermNode(String variable) {
this(variable, new ArrayList<TermNode>(), TermTypeEnum.VARIABLE);
}
public TermNode(Operator operator, List<TermNode> children) {
this(operator.getOperator(), children, TermTypeEnum.OPERATOR);
}
public TermNode(Function function, List<TermNode> children) {
this(function.getName(), children, TermTypeEnum.FUNCTION);
}
public TermNode(String value, List<TermNode> children, TermTypeEnum type) {
this.value = value;
this.children = children;
this.type = type;
}
public TermNode(TermNode node) {
this.value = node.getValue();
this.children = node.getChildren();
this.type = node.getType();
}
/**
*
* @return The value of this {@link TermNode}.
*/
public String getValue() {
return value;
}
/**
*
* @return The {@link List} of arguments for this {@link TermNode}.
*/
public List<TermNode> getChildren() {
return children;
}
/**
*
* @return The {@link TermTypeEnum} of this {@link TermNode}.
*/
public TermTypeEnum getType() {
return type;
}
/**
*
* @return True, if this {@link TermNode} represents a {@link ComplexNumber}.
*/
public boolean isNumber() {
return this.type == TermTypeEnum.NUMBER;
}
/**
*
* @return True, if this {@link TermNode} represents a variable.
*/
public boolean isVariable() {
return this.type == TermTypeEnum.VARIABLE;
}
/**
*
* @return True, if this {@link TermNode} represents an {@link Operator}.
*/
public boolean isOperator() {
return this.type == TermTypeEnum.OPERATOR;
}
/**
*
* @return True, if this {@link TermNode} represents a {@link Function}.
*/
public boolean isFunction() {
return this.type == TermTypeEnum.FUNCTION;
}
/**
*
* @return A {@link HashSet} object to compare two {@link TermNode} elements in equality.
*/
public HashSet<TermNode> getHash() {
return new HashSet<>(children);
}
}
爲了簡化像x + x + x + x
或sin(x) * sin(x)
我已經開始執行,其更新像x + x + x + x
一個節點到4 * x
節點的方法的表達式。
首先表達,我將提供一個例子用表達x + x + x + x
:
計算反向polnish符號/後修復順序的表達。
結果是
x x x x + + +
。用
TermNodes
(參見上面的代碼TermNode
)創建表達式樹/術語樹。算法是以下之一:public void evaluate() { Stack<TermNode> stack = new Stack<TermNode>(); for(String token : rpn) { if(OperatorUtil.containsKey(token)) { Operator operator = OperatorUtil.getOperator(token); List<TermNode> children = new ArrayList<TermNode>() {{ add(stack.pop()); add(stack.pop()); }}; TermNode node = simplifyOperator(operator, children); stack.push(node); } else if(FunctionUtil.containsKey(token.toUpperCase())) { Function function = FunctionUtil.getFunction(token.toUpperCase()); List<TermNode> children = new ArrayList<TermNode>(function.getNumParams()); for(int i = 0; i < function.getNumParams(); i++) { children.add(stack.pop()); } TermNode node = simplifyFunction(function, children); stack.push(node); } else { if(VariableUtil.containsUndefinedVariable(token.toUpperCase())) { stack.push(new TermNode(token)); } else { stack.push(new TermNode(new ComplexNumber(token))); } } } }
某處在
simplifyOperator
方法我想摺疊具有相同的值的變量。對於上面的表達式中,樹是這個樣子:_______ OPERATOR _______ / "+" \ / / \ \ VARIABLE VARIABLE VARIABLE VARIABLE "x" "x" "x" "x"
的目標是通過在
TreeNode
評估children
領域這棵樹轉換爲簡單的樹:這個表達式由一個OPERATOR
TermNode與運營商+
與。其中包含了VARIABLE
TermNode與價值x
倍(未四次相同TermNode兒童List<TermNode>
,僅有4 TermNodes具有完全相同的價值觀,兒童和類型下面是當我的問題進來:private TermNode rearrangeTerm(Operator operator, List<TermNode> children) { Map<TermNode, Integer> occurrences = children.stream() .collect(Collectors.groupingBy(term -> term, Collectors.summingInt(term -> 1))); List<Pair<TermNode, Integer>> simplification = occurrences.entrySet().stream() .map(entry -> new Pair<TermNode, Integer>(entry.getKey(), entry.getValue())).collect(Collectors.toList()); List<TermNode> rearranged = simplification.stream().map(pair -> rearrangeTerm(operator, pair)).collect(Collectors.toList()); return new TermNode(operator.getOperator(), rearranged, TermTypeEnum.OPERATOR); }
此方法正在被傳遞的參數
rearrangeTerm(operator, children)
到方法,其中,操作者是我們+
運營商和children
是我們的含有可變x
四倍TermNode
元素列表調用。此時
term -> term
Collectors.groupingBy
不會將TermNode元素按其字段值(值,子級和類型)分組,而是將其作爲TermNode引用自身。所以問題是,我怎麼能TermNode
元素由他們的字段(兩個TermNode
元素是相等的,如果所有他們的領域匹配(在子列表中的元素的順序可能是不同的,但重要的是,發生的每個TermNode
匹配的子項列表中的元素,當然TermNode
類型也必須匹配,這裏的問題只是如何更改rearrangeTerm
方法,以便Map僅包含一個條目(「x」, 4)用於表達x + x + x + x
?
您能否提供一個代數表達式以及您希望它產生的對象列表?根據您對node1的定義,「對(node1,4),Pair(node2,2)}」對應的代數表達式是什麼,即四次「x」和兩次「sin(x) node2'? –
@AlexandreDupriez修改了我的OP並添加了一個完整的示例。 – CRoemheld
我正在投票關閉這個簡單的事實,即您提供的代碼無法編譯 - 缺少大量的類。但是,如果你添加那些你的問題還是模糊的,你可以添加更多的「範圍」,使其更好 – Eugene