用于比较彼此之间的树的树结构

时间:2013-11-22 08:12:30

标签: java data-structures tree comparison treenode

我正在寻找一棵最适合我用例的树。树应包含硬件类型的元素,其中包含变量 ElementType

enum ElementType{
    Microcontroller;
    Core;
    Memory;
    Sensor;
    Pin;
    Network;
}

节点应以Hardware元素的 ElementType 命名:

enter image description here

一旦我构建了几棵树(如上图所示),我想将它们相互比较,并检查一棵树是否是另一棵树的一部分。例如。上面的树应该与下面的树进行比较,结果它应该给我回来,第一棵树是第二棵树的一部分。树应该通过它们的节点名称( ElementType )进行比较,因为每个树之间的底层对象不同:

enter image description here

java中是否有任何树形结构符合我的要求?

2 个答案:

答案 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;
   } 
}