[英]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.