我正在寻找一种比较两棵树的算法,并检查on树是否是另一棵树的子树。
我首先提供了一个自己的树实现,它具有以下结构:
public class PlatformTree {
private HwNode root;
.......
}
public class HwNode {
private HwNode parent;
private ElementType elementType;
private Hardware hw;
private List<Node> children = new ArrayList<Node>();
public Node(Node parent, ElementType elementType, Hardware hw) {
...
}
public void addChild(Node child) {
children.add(child);
}
....
以下图片应该为您提供概述:
树1
Tree2
如图所示,我想检查Tree1中是否包含Tree1的所有子树。 树的根项只是虚拟元素,用于访问子树。
我总是检查Tree2中是否包含Tree1的子树。 Tree1类型的节点总是有一个后继(Microcontroller.Memory),而Tree2类型的节点可以有几个后继(Microcontroller.Memory / Memory / Memory)。
ElementType确定节点是否相等。
如果所有子树都包含在另一个树中,则比较方法应返回 True 。否则它应该返回 False 。我现在花了很长时间来提供算法,但我估计递归调用仍有一些问题。这就是我到目前为止所做的:
类TreePlatform:
public boolean containsSubTree(PlatformTree tree1) {
Boolean b = true;
// check all subtrees of Tree1
if (tree1.getRoot() != null && getRoot() != null) {
for (HwNode subRootNode : tree1.getRoot().getChildren()) {
b = getRoot().containsSubTree(subRootNode);
}
} else {
return false;
}
return b;
}
班级HwNode
public boolean containsSubTree(HwNode abstractNode) {
for (HwNode subRootNode : getChildren()) {
if (hasSubTree(subRootNode, abstractNode)) {
return true;
}
}
return false;
}
private boolean hasSubTree(HwNode subRootNode, HwNode abstractNode) {
if (subRootNode.getElementType() != abstractNode.getElementType()) {
return false;
}
if (!abstractNode.getChildren().isEmpty()) {
if (!subRootNode.getChildren().isEmpty()) {
HwNode abstractSubNode = abstractNode.getChildren().get(0);
for (HwNode subNode : subRootNode.getChildren()) {
if (!hasSubTree(subNode, abstractSubNode)) {
return false;
}
}
} else {
return false;
}
} else if (subRootNode.getChildren().isEmpty()) {
return true;
}
return true;
}
我对我的算法感到不满意,但此刻我仍然感到困惑,不知道如何解决这个问题。我有什么想法可以比较两棵树吗?
答案 0 :(得分:3)
Aight,所以问题是在另一棵树中寻找一棵树。这是一个标准的面试问题,如果树有一个订单,但你的没有,这使事情变得更加复杂。类似地,如果我们正在寻找树同余而不是包含,并且如果我们可以使用Kelly's Theorem作为Adam Gent在OP的注释中指示并且只计算子树。
为了清楚起见,我打算将两棵树称为模式树和目标树。我们想测试模式树是否是目标树的子树。
你的方法是(虽然我可能会理解)模式树中的节点P等同于目标树中的节点T iff P的每个子节点等于T中的节点。事实是,这有一个问题:如果P与子项具有两个相同的子树,该怎么办?它与只有一个子树的节点T匹配!
现在这不是一个致命的缺陷:我们可以通过在我们认为找到匹配时删除T的子树来调整这种方法,然后如果后来证明我们错了就进行一堆回溯。但是,这有点像组合爆炸。
更好的方法是从头开始而不是自上而下。我的意思是
这是在二次时间,这不是很好,但通常的谷歌搜索并没有揭示更好的算法(主要是因为二叉树/有序树变体淹没了搜索空间)。如果有人知道更好,我会很高兴听到它。使用凯利的定理来反对所有的子树,我认为这是天真的,但是有一些记忆可能也会归结为二次方。