具有泛型的树数据结构

时间:2014-04-30 14:18:44

标签: c# .net oop collections

我现在正在桌子上敲打几个小时,但是在C#中实现树形结构似乎太愚蠢了。

  1. 有两种类型的节点,我称之为NodeNodeCollection
  2. NodeNodeCollection都可以有父NodeCollection
  3. NodeCollection可以有一组子节点,可以是NodeNodeCollection
  4. Node不能有任何孩子。
  5. 没有父级的NodeNodeCollection被视为根节点
  6. Node具有任何任意类型的值,使用泛型

    • NodeCollection
      • NodeCollection
        • 节点
        • 节点
        • NodeCollection
          • 节点
          • NodeCollection
            • 节点
            • 节点
          • NodeCollection
        • 节点
  7. BCL的集合类型是否有此目的?到目前为止我所拥有的:

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

    这个解决方案“有效”,但我不能只是走下树,因为NodeBase没有提供任何子项。我必须验证类型以查明子节点是否为NodeCollection,但如果不是,则无法正确转换Node,因为它可能是未知类型。

2 个答案:

答案 0 :(得分:5)

最简单的选择是只有一个Node类(而不是有两种类型的节点,将叶子与非叶子节点分开),并让你的叶子节点只有一个空的子集合而不是根本没有收集。

如果出于其他原因拥有这两种类型的节点很重要,那么您希望让它们都实现一个定义子集合的接口,叶子节点将返回到该接口一个空的集合。

答案 1 :(得分:0)

为了处理Node没有到集合的链接,我使用了一个名为&#34; HasChildren&#34;的抽象基类属性。允许检查,并确保如果您忘记检查并尝试访问子项,具体的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"); } }
}

我使用抽象基类方法中的Add方法具体实现来计算要添加的内容,以及如何对我来说,它还负责将项目添加到NodeCollections的集合排序,并在需要时强制执行唯一性