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