具有泛型的树数据结构

本文关键字:数据结构 泛型 | 更新日期: 2023-09-27 18:00:52

我已经在桌子上敲了好几个小时了,但我似乎太愚蠢了,无法在C#中实现树结构。

  1. 有两种类型的节点,我称它们为NodeNodeCollection
  2. NodeNodeCollection都可以有一个父NodeCollection
  3. NodeCollection可以具有子节点的集合,这些子节点是NodeNodeCollection
  4. Node不能有任何子项
  5. 没有父节点的NodeNodeCollection被认为是根节点
  6. Node具有任意类型的值,使用泛型完成

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

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不提供任何childreen。我必须验证类型以确定子节点是否是NodeCollection,但如果不是,我就无法正确地强制转换Node,因为它可能是未知类型。

具有泛型的树数据结构

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

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

为了处理没有到集合的链接的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"); } }
}

我使用抽象基类方法的Add方法具体实现来确定要添加什么以及如何添加,对我来说,这还负责将项添加到NodeCollections的集合排序,并在需要时强制执行唯一性。