简体   繁体   English

具有泛型的树数据结构

[英]Tree data structure with generics

I'm banging my head on the desk for hours now, but it seems like I'm too stupid to implement a tree structure in C#. 我现在要在桌子上敲几个小时,但似乎太愚蠢了,无法在C#中实现树形结构。

  1. There are 2 types of nodes, I call them Node and NodeCollection . 有两种类型的节点,我称它们为NodeNodeCollection
  2. Both Node and NodeCollection can have a parent NodeCollection NodeNodeCollection都可以有一个父NodeCollection
  3. A NodeCollection can have a collection of child nodes, which are either Node or NodeCollection NodeCollection可以具有子节点的集合,这些子节点可以是NodeNodeCollection
  4. A Node cannot have any childs. Node不能有任何子Node
  5. A Node or NodeCollection without parent is considered to be the root node 没有父NodeNodeCollection被认为是根节点
  6. A Node has a value of any arbitary type, done with generics Node具有泛型完成的任意类型的值

    • NodeCollection NodeCollection
      • NodeCollection NodeCollection
        • Node 节点
        • Node 节点
        • NodeCollection NodeCollection
          • Node 节点
          • NodeCollection NodeCollection
            • Node 节点
            • Node 节点
          • NodeCollection NodeCollection
        • Node 节点

Is there a collection type from the BCL that serves this purpose? 是否有来自BCL的收集类型用于此目的? What I have so far: 到目前为止,我有:

public abstract class NodeBase {

    protected NodeCollection Parent { get; set; }

}

public class Node<T> : NodeBase {

    public string Key { get; set; }
    public T Value { get; set; }

}

public class NodeCollection : NodeBase {

    public ICollection<NodeBase> Children { get; set; }

}

This solution 'works', however I cannot just walk down the tree as NodeBase doesn't offer any childreen. 这个解决方案“行得通”,但是由于NodeBase不提供任何子项,我不能随便走这棵树。 I have to validate the type to find out if the child node is a NodeCollection , but if it is not, I can't properly cast the Node because it might be of unknown type. 我必须验证类型以查明子节点是否为NodeCollection ,但如果不是,则无法正确转换Node因为它可能是未知类型。

The easiest option is to just have one Node class (rather than having two types of nodes, to separate leaves from non-leaf nodes), and to have your leaf nodes just have an empty collection of children rather than no collection at all. 最简单的选择是只具有一个Node类(而不是具有两种类型的节点,以将叶子与非叶子节点分开),并使叶子节点仅具有空的子级集合,而不是根本没有任何子集。

If it's important to have the two types of nodes for other reasons, then you'd want to have both of them implement an interface that defines a collection of children, to which the leaf nodes will return an empty collection. 如果由于其他原因而拥有两种类型的节点很重要,那么您希望它们都实现一个定义子项集合的接口,叶节点将向该子项返回一个空集合。

For dealing with the Node not having a link to the collection, I use an abstract base class property called "HasChildren" to allow for checking, and ensure that the concrete Node implementation throws an exception if you forgot to check and tried accessing the children. 为了处理没有链接到集合的Node,我使用了一个称为“ HasChildren”的抽象基类属性来进行检查,并确保如果忘记检查并尝试访问子级,则具体的Node实现会引发异常。

public abstract class NodeBase<T> {
  public abstract bool HasChildren { get; }
  public abstract ICollection<T> Children { get; set; }
}
public class NodeCollection<T> : NodeBase<T> {
  public override bool HasChildren { get { return true; } }
  public override ICollection<T> Children { get; set; }
}
public class Node<T> : NodeBase<T> {
  public override bool HasChildren { get { return false; } }
  public override ICollection<T> Children { get { throw new Exception("blah"); } set { throw new Exception("blah"); } }
}

I use an Add method concrete implementation from an abstract base class method to work out what to add, and how, for me this also takes care of collection sorting for adding items to NodeCollections, and enforces uniqueness if required. 我从抽象基类方法中使用Add方法的具体实现来计算要添加的内容,以及对我而言,该方法还负责将项目添加到NodeCollections的集合排序,并在需要时实施唯一性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM