我正在使用Java编写代码,该代码使用无序的根树,每个节点可能有任意数量的子节点。给定树T和子树S,我希望能够找到所有与S匹配的T中的子树(即与S同构的T中的所有子树)。
如果T的一个子树与S同构,则S的节点可以映射到T的节点,使得S的边映射到T中的边。
关于如何查找树是否包含另一个子树,已经有一个previous question,但是我想要能够找到T中与S匹配的所有子树。此外,我希望能够将每个匹配中T中的每个节点映射到S中相应的节点。
也就是说,当找到匹配时,它不仅应返回指向T中根据S匹配的树的节点的指针,而且应该返回类似于指向节点对的列表 [(T1,S1),(T2,S2),...(Tn,Sn)] 的匹配,其中T1是指向在子树中映射到节点S1的T中的节点的指针,依此类推。
或者,可以简单地返回一对值的列表,因为树T和子树S中的每个节点都与其唯一的整数标识符相关联。
例如:
给定树T如下:
以下匹配列表应返回:
[(a,x),(b,y),(c,z)] [(a,x),(b,y),(d,z)] [(a,x),(c,y),(d,z)]
有人能提供任何如何完成这个任务的示例代码吗?
编辑(与Chris Kannon的评论相关):
我想你想让别人为你编码答案?你做到了多远?你写了什么代码?- Chris Kannon 1小时前
我有以下代码,当运行时,建立一个指向树中匹配给定子树的子树根节点的指针列表(matchesList)。但是,在同一节点处可能有多个以相同方式匹配的子树,并且当前每个节点最多只会添加一次到matchesList中,无论有多少匹配项在那里。
此外,我无法弄清楚如何建立上述在子树中的节点和在原始树中找到的匹配节点之间的映射。
代码成功检测到第一棵树的顶部节点和第一棵树的第三个子节点存在匹配。然而,实际上有3个与顶部节点匹配的子树,而不仅仅是一个。此外,代码没有建立树中节点和子树中节点之间的映射,我无法弄清如何实现这一点。
有人可以提供如何做到这一点的建议吗?
如果T的一个子树与S同构,则S的节点可以映射到T的节点,使得S的边映射到T中的边。
关于如何查找树是否包含另一个子树,已经有一个previous question,但是我想要能够找到T中与S匹配的所有子树。此外,我希望能够将每个匹配中T中的每个节点映射到S中相应的节点。
也就是说,当找到匹配时,它不仅应返回指向T中根据S匹配的树的节点的指针,而且应该返回类似于指向节点对的列表 [(T1,S1),(T2,S2),...(Tn,Sn)] 的匹配,其中T1是指向在子树中映射到节点S1的T中的节点的指针,依此类推。
或者,可以简单地返回一对值的列表,因为树T和子树S中的每个节点都与其唯一的整数标识符相关联。
例如:
给定树T如下:
a
/ \
b c
/ \
d e
并且子树S为:
x
/ \
y z
应返回以下匹配列表:
[(a,x),(b,y),(c,z)] [(b,x),(d,y),(e,z)]
唯一的匹配是由T中的节点集确定的,而不是T和S之间的映射关系。
因此,以下匹配:
[(a,x),(b,z),(c,y)]
被视为与
[(a,x),(b,y),(c,z)]
重复,因为它们具有相同的来自T的节点集(a,b,c),因此只应返回其中一个匹配。
作为另一个示例,给定树T:
a
/|\
b c d
和子树S:
x
/ \
y z
以下匹配列表应返回:
[(a,x),(b,y),(c,z)] [(a,x),(b,y),(d,z)] [(a,x),(c,y),(d,z)]
有人能提供任何如何完成这个任务的示例代码吗?
编辑(与Chris Kannon的评论相关):
我想你想让别人为你编码答案?你做到了多远?你写了什么代码?- Chris Kannon 1小时前
我有以下代码,当运行时,建立一个指向树中匹配给定子树的子树根节点的指针列表(matchesList)。但是,在同一节点处可能有多个以相同方式匹配的子树,并且当前每个节点最多只会添加一次到matchesList中,无论有多少匹配项在那里。
此外,我无法弄清楚如何建立上述在子树中的节点和在原始树中找到的匹配节点之间的映射。
package Example;
import java.util.LinkedList;
import java.util.Vector;
public class PartialTreeMatch {
public static void main(String[] args) {
NodeX testTree = createTestTree();
NodeX searchTree = createSearchTree();
System.out.println(testTree);
System.out.println(searchTree);
partialMatch(testTree, searchTree);
}
static LinkedList<NodeX> matchesList = new LinkedList<NodeX>();
private static boolean partialMatch(NodeX tree, NodeX searchTree) {
findSubTreeInTree(tree, searchTree);
System.out.println(matchesList.size());
for (NodeX n : matchesList) {
if (n != null) {
System.out.println("Found: " + n);
}
}
return false;
}
private static NodeX findSubTreeInTree(NodeX tree, NodeX node) {
if (tree.value == node.value) {
if (matchChildren(tree, node)) {
matchesList.add(tree);
}
}
NodeX result = null;
for (NodeX child : tree.children) {
result = findSubTreeInTree(child, node);
if (result != null) {
if (matchChildren(tree, result)) {
matchesList.add(result);
}
}
}
return result;
}
private static boolean matchChildren(NodeX tree, NodeX searchTree) {
if (tree.value != searchTree.value) {
return false;
}
if (tree.children.size() < searchTree.children.size()) {
return false;
}
boolean result = true;
int treeChildrenIndex = 0;
for (int searchChildrenIndex = 0; searchChildrenIndex < searchTree.children
.size(); searchChildrenIndex++) {
// Skip non-matching children in the tree.
while (treeChildrenIndex < tree.children.size()
&& !(result = matchChildren(tree.children
.get(treeChildrenIndex), searchTree.children
.get(searchChildrenIndex)))) {
treeChildrenIndex++;
}
if (!result) {
return result;
}
}
return result;
}
private static NodeX createTestTree() {
NodeX subTree2 = new NodeX('A');
subTree2.children.add(new NodeX('A'));
subTree2.children.add(new NodeX('A'));
NodeX subTree = new NodeX('A');
subTree.children.add(new NodeX('A'));
subTree.children.add(new NodeX('A'));
subTree.children.add(subTree2);
return subTree;
}
private static NodeX createSearchTree() {
NodeX root = new NodeX('A');
root.children.add(new NodeX('A'));
root.children.add(new NodeX('A'));
return root;
}
}
class NodeX {
char value;
Vector<NodeX> children;
public NodeX(char val) {
value = val;
children = new Vector<NodeX>();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('(');
sb.append(value);
for (NodeX child : children) {
sb.append(' ');
sb.append(child.toString());
}
sb.append(')');
return sb.toString();
}
}
上述代码试图在以下内容中找到所有的子图:
A
/|\
A A A
/ \
A A
匹配哪些:
A
/ \
A A
代码成功检测到第一棵树的顶部节点和第一棵树的第三个子节点存在匹配。然而,实际上有3个与顶部节点匹配的子树,而不仅仅是一个。此外,代码没有建立树中节点和子树中节点之间的映射,我无法弄清如何实现这一点。
有人可以提供如何做到这一点的建议吗?