【问题标题】:Tree data structure with generics具有泛型的树数据结构
【发布时间】:2014-06-16 22:09:45
【问题描述】:

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

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

    • 节点集合
      • 节点集合
        • 节点
        • 节点
        • 节点集合
          • 节点
          • 节点集合
            • 节点
            • 节点
          • 节点集合
        • 节点

是否有来自 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,因为它可能是未知类型。

【问题讨论】:

  • 您还没有提出问题,也没有展示您迄今为止所做的尝试,或者描述了您面临的问题。
  • @JonSkeet 我正在处理,目前正在编辑问题。

标签: c# .net oop collections


【解决方案1】:

为了处理没有指向集合的链接的节点,我使用了一个名为“HasChildren”的抽象基类属性来允许检查,并确保如果您忘记检查并尝试访问,具体的节点实现会引发异常孩子们。

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 的集合排序,并在需要时强制执行唯一性。

【讨论】:

  • 链表有什么帮助?
  • 根据 OP,它是“来自 BCL 的用于此目的的集合类型”,并且在 this implementation 中非常有效地使用
  • 这是一种 BCL 类型,但 它不能用于此目的。它现在可以帮助他访问任何特定节点的所有子节点。让LinkedList 成为代表孩子的ICollection 的具体实现并没有真正的意义。它与List 没有什么不同,只是它在典型用例中的性能很可能会更差。 任何实现ICollection 都可以。
  • 让基类同时实现ChildrenHasChildren 就涵盖了这一点。 LinkedList 可以用作底层存储,而不是滚动您自己的 Count、First、Last、AddX、Remove、Clear ...
  • 好吧,HasChildren 根本不需要,可以简单地拥有一个空的Children 集合。是的,从所有节点类型都可以访问它是关键,但这不在您的答案中,尽管这是问题的答案。关于LinkedList 的一切都与问题无关。他只需要为Children 集合实现ICollection,他可以随意使用他想要的任何东西,只要它实现ICollection。没有令人信服的理由使用LinkedList(也有一些令人信服的理由不使用)。
【解决方案2】:

最简单的选择是只拥有一个Node 类(而不是拥有两种类型的节点,以将叶子与非叶子节点分开),并且让您的叶子节点只有一个空的子节点集合而不是没有完全收藏。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-02
    • 2014-03-11
    • 1970-01-01
    • 1970-01-01
    • 2018-05-04
    • 1970-01-01
    相关资源
    最近更新 更多