我正在寻找一棵最适合我用例的树。树应包含硬件类型的元素,其中包含变量 ElementType :
enum ElementType{
Microcontroller;
Core;
Memory;
Sensor;
Pin;
Network;
}
节点应以Hardware元素的 ElementType 命名:
一旦我构建了几棵树(如上图所示),我想将它们相互比较,并检查一棵树是否是另一棵树的一部分。例如。上面的树应该与下面的树进行比较,结果它应该给我回来,第一棵树是第二棵树的一部分。树应该通过它们的节点名称( ElementType )进行比较,因为每个树之间的底层对象不同:
java中是否有任何树形结构符合我的要求?
答案 0 :(得分:1)
据我所知,没有一个结构,但它很容易实现
public class Tree {
private Node root;
public boolean containsSubTree(Tree other) {
return root.containsSubTree(other.root);
}
}
public class Node {
private Node parent;
private ElementType elementType;
private List<Node> children = new ArrayList<Node>();
public Node(Node parent, ElementType elementType) {
...
}
public void addChild(Node child) {
children.add(child);
}
protected boolean equalsIgnoreParent(Node other) {
if (elementType != other.elementType) return false;
if (children.size() != other.children.size()) return false;
for (int i = 0; i < children.size(); ++ i) {
// recursive step
if (!children.get(i).equalsIgnoreParent(other.children.get(i)) {
return false;
}
}
return true;
}
public boolean containsSubTree(Node other) {
if (equalsIgnoreParent(other)) return true;
for (Node child : children) {
// recursive step
if (child.containsSubTree(other)) return true;
}
return false;
}
}
然后只需调用tree1.containsSubTree(tree2)进行检查。
如果您想忽略孩子的顺序,您可能会将孩子存储为SortedSet,这需要适当的Comparator。
我的解决方案是使用recursion实施的,这可能导致深call stack。我确信它可以在没有递归的情况下实现....我只是不能被打扰:)
答案 1 :(得分:0)
我在另一个答案中得到了错误的想法。这是另一次尝试:
public class Node {
// LinkedHashMap preserves order in which nodes were added
private Map<ElementType, Node> childMap = new LinkedHashMap<ElementType, Node>();
private ElementType elementType;
public void addChild(Node node) {
if (childMap.containsKey(node.elementType)) {
throw new IllegalStateException("Duplicates not allowed");
}
childMap.put(node.elementType, node);
}
public Collection<Node> getChildren() {
return childMap.values();
}
/**
* Ensure all nodes in other are in this node.
* Ignore any extra elements in this that are not in other
*/
protected boolean isSameIgnoreExtras(Node other) {
if (this.elementType != other.elementType) return false;
if (this.childMap.size() < other.childMap.size()) return false;
for (Node otherChild : other.getChildren()) {
Node thisChild = childMap.get(otherChild.elementType);
if (thisChild == null) {
return false;
}
// recursive step
if (!thisChild.isSameIgnoreExtras(otherChild)) {
return false;
}
}
return true;
}
public boolean containsSubTree(Node other) {
if (isSameIgnoreExtras(other)) {
return true;
}
for (Node child : getChildren()) {
// recursive step
if (child.containsSubTree(other)) {
return true;
}
}
return false;
}
}