【问题标题】:Object oriented design, designing a tree面向对象设计,设计一棵树
【发布时间】:2013-05-24 03:38:11
【问题描述】:

我正在用 Java 创建一个(非典型)树,它将由三个类组成:节点、分支和叶

每个节点都将其连接的分支存储在一个 HashSet 中。该分支应该导致一个后代节点或叶子,但我不知道如何编码。即使我永远不会同时使用这两个变量,我是否会在分支类中有两个单独的变量,一个 Node 和一个 Leaf,以及两组 getter 和 setter?在这方面是否有最佳实践?

我在想也许可以创建同一个超类的节点和叶子类,但它们在代码方面绝对没有共同点(即不同的变量类型、函数等)。

编辑: 节点引用分支和 每个 Branch 引用一个 Node 或 Leaf

【问题讨论】:

  • 最简单的方法是让每个节点都包含一组对子节点的引用和一个数据引用(即Node<T>)。如果除了叶节点之外不能有数据,则在运行时强制执行该规则。除了数据类之外,您只需要一个类Node<T>
  • 分支是有目的的。我了解基本方法,这就是为什么我说这个是非典型的。

标签: java oop tree


【解决方案1】:

我可能会选择这样的东西:

  interface BranchDestination {
    boolean isLeaf();
  }

  class Node implements BranchDestination {
    private Set branches;
    public boolean isLeaf() {
      return false;
    }
    ...
  }

  class Leaf implements BranchDestination {
    public boolean isLeaf() {
      return true;
    }
    ...
  }

  class Branch {
    BranchDestination destination;
    ...
  }

【讨论】:

    【解决方案2】:

    我确实喜欢为叶/节点类定义interface 并在每个类中实现该接口的想法。我会在该接口中定义一个简单的函数(下面的语法可能有误,但它是伪代码):

    interface BranchItem {
        public object[] GetVals();
    }
    
    public class Branch
    {
       public BranchItem item;
    }
    
    public class Leaf implements BranchItem
    {
        private object myVal = <your data here>;
    
        public object[] GetVals() {
          return new object[] { myVal };
        }
    }
    
    public class Node implements BranchItem
    {
        private myBranches[] = <List of Branches>;
    
        public object[] GetVals() {
    
          object[] myArray = new object[];
          foreach (BranchItem b in myBranches)
          {
             myArray.addTo(b.item.GetVals());
          }
    
          return myArray;
        }
    }
    

    遍历您的节点时,只需遍历分支并调用GetVals()

    Leaf 类将简单地返回它的存储值。

    Node 类将递归循环其分支,在每个分支上调用 GetVals() 并将其添加到它自己的返回数组中。

    这只是一个简单的实现。如果您想要排序顺序、处理冲突或重复数据,或者任何类似性质的事情,它可能会变得更加复杂。

    【讨论】:

      【解决方案3】:

      使用基本信息制作 Leaf 类。

      创建包含对 Leafs 的引用的 Branch 类。

      创建包含对 Brahces 的引用的 Node 类。

      然后尝试查找递归以及如何使用它来制作这样的构造:)

      这是我的尝试。虽然不是很优雅,但它可以完成工作。

      这是 Leaf 类:

      public class Leaf {
          private String text;
      
          public Leaf(String text) {
              this.text = text;
          }
      
          public String getText() {
              return text;
          }
      
          public void setString(String newString) {
              text = newString;
          }
      
          @Override
          public String toString() {
              return text;
          }
      }
      

      这里是分支类:

      public class Branch<T> {
          private String text;
          private HashSet<T> list;
      
          public Branch(String text) {
              this.text = text;
              list = new HashSet<>();
          }
      
          public String getText() {
              return text;
          }
      
          public void setText(String newText) {
              text = newText;
          }
      
          public HashSet<T> getHashSet() {
              return list;
          }
      
          public void setHashSet(HashSet<T> newList) {
              list = newList;
          }
      
          public String getAllLeaves() {
              StringBuilder sb = new StringBuilder();
              sb.append(text).append("\n");
              for(T t : list) {
                  sb.append("\t\t");
                  sb.append(t.toString()).append("\n");
              }
              return sb.toString();
          }
      
          @Override
          public String toString() {
              return text;
          }
      }
      

      最后是 Node 类:

      public class Node<T> {
          private String text;
          private HashSet<T> list;
      
          public Node(String text) {
              this.text = text;
              list = new HashSet<>();
          }
      
          public String getText() {
              return text;
          }
      
          public void setText(String newText) {
              text = newText;
          }
      
          public HashSet<T> getHashSet() {
              return list;
          }
      
          public void setHashSet(HashSet<T> newList) {
              list = newList;
          }
      }
      

      小程序试一试:

      public class TreeConstruct {
          public static void main(String[] args) {
              Leaf l1 = new Leaf("Leaf 1");
              Leaf l2 = new Leaf("Leaf 2");
              Leaf l3 = new Leaf("Leaf 3");
              Leaf l4 = new Leaf("Leaf 4");
      
              Branch<Leaf> b1 = new Branch("Branch 1");
              Branch<Leaf> b2 = new Branch("Branch 2");
      
              Node<Branch> n1 = new Node("Node 1");
      
              b1.getHashSet().add(l1);
              b1.getHashSet().add(l2);
              b1.getHashSet().add(l3);
              b2.getHashSet().add(l4);
      
              n1.getHashSet().add(b1);
              n1.getHashSet().add(b2);
      
              System.out.println(printNodeTree(n1));
          }
      
          public static String printNodeTree(Node<Branch> n) {
                  StringBuilder sb = new StringBuilder();
                  sb.append(n.getText()).append("\n");
                  for(Branch b : n.getHashSet()) {
                      sb.append("\t");
                      sb.append(b.getAllLeaves());
                  }
                  return sb.toString();
              }
      }
      

      输出将是:

      Node 1
              Branch 1
                      Leaf 1
                      Leaf 3
                      Leaf 2
              Branch 2
                      Leaf 4
      

      希望这会有所帮助!

      【讨论】:

      • 您能详细说明一下吗?我知道我将使用递归来使用节点和分支构建树的主要部分,但在底部会有与主节点不同用途的叶子。
      • 你必须用图形或文字来表示它吗?
      • @Vipar:嗯,声明这样的类型确实涉及类型递归,但是程序员的词汇表中通常不会找到这个术语(不过,请再次参阅 Wirth 的“算法 + 数据”)。但是,使用这样的结构肯定需要递归函数。
      • 分支类最常引用节点,然后只在末尾引用叶子。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多