Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有泛型的树数据结构_C#_.net_Oop_Collections - Fatal编程技术网

C# 具有泛型的树数据结构

C# 具有泛型的树数据结构,c#,.net,oop,collections,C#,.net,Oop,Collections,我在办公桌上忙了好几个小时,但似乎我太笨了,不能在C#中实现树结构 有两种类型的节点,我称它们为Node和NodeCollection Node和NodeCollection都可以有父节点NodeCollection NodeCollection可以具有子节点的集合,这些子节点可以是Node或NodeCollection 节点不能有任何子节点 没有父节点的节点或节点集合被视为根节点 节点具有任意任意类型的值,由泛型完成 节点收集 节点收集 节点 节点 节点收集 节点 节点收集 节点 节

我在办公桌上忙了好几个小时,但似乎我太笨了,不能在C#中实现树结构

  • 有两种类型的节点,我称它们为
    Node
    NodeCollection
  • Node
    NodeCollection
    都可以有父节点
    NodeCollection
  • NodeCollection
    可以具有子节点的集合,这些子节点可以是
    Node
    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; }
    
    }
    
    公共抽象类节点库{
    受保护的NodeCollection父项{get;set;}
    }
    公共类节点:NodeBase{
    公共字符串密钥{get;set;}
    公共T值{get;set;}
    }
    公共类节点集合:节点库{
    公共ICollection子项{get;set;}
    }
    

    这个解决方案“有效”,但是我不能只是沿着树走,因为
    节点库
    不提供任何childreen。我必须验证类型以确定子节点是否为
    节点集合
    ,但如果不是,我无法正确地强制转换
    节点
    ,因为它可能是未知类型。

    最简单的选择是只拥有一个
    节点
    类(而不是拥有两种类型的节点,以将叶节点与非叶节点分开),要使叶节点具有子节点的空集合,而不是完全没有集合


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

    最简单的选择是只使用一个
    节点
    类(而不是拥有两种类型的节点,将叶节点与非叶节点分开),以及让叶节点只拥有子节点的空集合,而不是根本没有集合


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

    为了处理没有到集合链接的节点,我使用了一个名为“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"); } }
    }
    
    公共抽象类节点库{
    公共抽象布尔有子对象{get;}
    公共抽象ICollection子项{get;set;}
    }
    公共类节点集合:节点库{
    公共重写bool haschilds{get{return true;}}
    公共重写ICollection子项{get;set;}
    }
    公共类节点:NodeBase{
    公共重写bool haschilds{get{return false;}}
    公共重写ICollection子项{get{throw new Exception(“blah”);}set{throw new Exception(“blah”);}
    }
    

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

    对于没有到集合的链接的节点,我使用一个抽象基类属性“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"); } }
    }
    
    公共抽象类节点库{
    公共抽象布尔有子对象{get;}
    公共抽象ICollection子项{get;set;}
    }
    公共类节点集合:节点库{
    公共重写bool haschilds{get{return true;}}
    公共重写ICollection子项{get;set;}
    }
    公共类节点:NodeBase{
    公共重写bool haschilds{get{return false;}}
    公共重写ICollection子项{get{throw new Exception(“blah”);}set{throw new Exception(“blah”);}
    }
    

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

    您还没有问过问题,也没有展示您迄今为止的尝试,也没有描述您遇到的问题'你在面对。@JonSkeet我在上面,正在编辑问题。你还没有问过问题,也没有展示你迄今为止的尝试,也没有描述你所面临的问题。@JonSkeet我在上面,正在编辑问题。链表有什么帮助?根据OP,它是“BCL中用于此目的的集合类型”",它在BCL类型中使用非常有效,但它不起作用。它现在可以帮助他访问任何特定节点的所有子节点。将
    LinkedList
    作为表示子节点的
    ICollection
    的具体实现并没有真正的意义。它与
    列表没有什么不同
    ,除了它在典型用例中的性能最差之外。
    ICollection
    的任何实现都可以。让基类同时实现
    Children
    hasschildren
    。LinkedList可以用作底层存储,而不是首先滚动您自己重新创建的计数,最后,AddX,Remove,Clear…嗯,根本不需要孩子,你可以简单点