[英]Equivalent subtree
我有兩棵樹。 樹節點定義為
class Node{
String treeId;
String type; //Each node has type which has fixed value. For example, its color: RED, BLANK, GREEN
Set<Node> children;
String ref; //The ref is a string and allowed value are "0", "1",..."10". The value is null if it is not leaf.
};
對於葉子,子集為空。
我想知道是否已經完成了一些有效的工作,如何為兩個給定的樹識別等效的子樹。 等效定義為:
1) Both subtree leaves are setsets leaves of original tree.
2) Both subtrees leaves have same ref value.
3) for non-leaves node, the equivalent refers to both node have same type and equivalent children.
謝謝。 如果有一些Java庫可以解決此問題,那就更好了。
輸入應該是兩個樹的根,而輸出是作為等效子樹的根的Node。 樹的高度為100〜,並且有500多個節點。
我現在所做的是為類Node添加了一個新字段。
class Cache{
Map<String, Set<String>> map = new LinkedHashMap<String, Set<Str>>();
}
映射的鍵是節點ID,而值是該節點ID的此節點可以到達的引用集。 初始化節點時啟動的緩存。
在isEquivalent比較階段,檢查兩個根的引用集之間是否存在重疊。 如果沒有返回false。
我認為這可以幫助減少比較空間的數量。
我不確定1) Both subtree leaves are leaves of original tree.
要求似乎與how to identify equivalent substree for two given tree.
相沖突how to identify equivalent substree for two given tree.
。 否則下面的遞歸方法應該能夠覆蓋其他兩個條件。 可以實現haveSameOriginalTree(r1, r2)
方法來滿足我無法理解的第一個條件。 r1
和r2
是需要檢查是否相等的兩個子樹的根。
bool areEquivalent(Node r1, Node r2)
{
if(r1.children == null && r2.children == null)
{
return (haveSameOriginalTree(r1, r2) && (r1.ref == r2.ref));
}
if((r1.children == null && r2.children != null) || (r1.children != null && r2.children == null))
{
return false;
}
// if here then both must be non-leaf nodes
if(r1.type != r2.type)
{
return false;
}
if(r1.children.getCount() != r2.children.getCount()) // not sure of correct syntax for Java Sets
{
return false;
}
for(int i=0; i<r1.children.getCount(); i++)
{
if(!areEquivalent(r1.children[i], r2.children[i])) // again please correct the syntax for Sets
{
return false;
}
}
return true;
}
讓我知道你的想法。
更新資料
這是上述解決方案的迭代版本。 它使用分配在堆上的堆棧數據結構,而不是推入函數的調用堆棧,因此與遞歸沒有太大區別,但仍然更好。 另外,由於我們僅保留對Node
的引用(而不是復制整個對象),因此如果我們已經將原始樹加載到內存中,那么這不應該是那么多的額外內存開銷。
bool areEquivalent(Node r1, Node r2)
{
Stack<Node> s1 = new Stack<Node>();
Stack<Node> s2 = new Stack<Node>();
Node n1, n2;
s1.Push(r1);
s2.Push(r2);
while(true) // Need a better check
{
if(s1.getCount() != s2.getCount())
{
return false;
}
if(s1.getCount() == 0) // if both stacks are empty then we've traversed both trees without failure.
{
return true;
}
n1 = s1.Pop();
n2 = s2.Pop();
if(!areEquivalentNodes(n1, n2))
{
return false;
}
foreach(Node child in n1.children)
{
s1.Push(child);
}
foreach(Node child in n2.children)
{
s2.Push(child);
}
}
}
// only checks the two nodes are equivalent. their childrens' equivalence will be handled by other calls to this method.
bool areEquivalentNodes(Node n1, Node n2)
{
if(n1.children.getCount() != n2.children.getCount())
{
return false;
}
if(n1.children.getCount() == 0) // if both are leaf nodes...
{
if(n1.ref != n2.ref)
{
return false;
}
}
else // both are non-leaf
{
if(n1.type != n2.type)
{
return false;
}
// the condition that children of non-leaf nodes be equivalent will be covered by subsequent calls this method...
}
return true;
}
請注意,這兩個解決方案,希望children
在同一順序兩個等價節點。 如果未訂購children
則在調用上述代碼之前,我們需要對它們進行排序。
讓我知道這是否更好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.