如何形成我的节点和树通用类

我有一个IList

Category类型来自SQL Server中的Category表:

表:类别

CategoryID,ParentCategoryID

在一张桌子上如此典型的层次结构。

因此,如果我有这个包含节点关系的类别的IList,那么我试图弄清楚这是如何适合制作像很多人一样的节点和树。 那么构造函数看起来会如何根据用法创建这个类?

我对Generics来说并不是一个很难的核心。 我认为在这里创建一个通用的Node类和Tree类是有道理的,所以我可以在将来重用其他树类型。

所以如果我有这样的东西,T如何被使用以及我从中获益?

(伪代码在这里)

 public class Node ... Node _parentNode; List<Node> _children; private void SetParentNode(T) private void AddChild(T) ... etc. 

试图理解这里的概念,为什么Generic Node类将用于像Childeren等进入的任何类型,包含子/父关系(int Ids)

UPDATE

所以在这里遇到GroupBy建议的问题。 看看我试图用你的例子做什么:

首先,我在Tree类中拥有此属性:

public Dictionary,IList >> ParentNodeAndRelatedChildrenFlattenedMap {get; 私人集; }

并且传入我的类的构造函数是一个IList依赖项,我转换(循环并为它们中的每一个创建一个新的Node)到IList>

现在我正在尝试通过Node.ParentId对该列表进行分组,以便我在父节点上进行分组,并且由于每个节点都有其子属性,因此很容易找出相关子节点对这些父节点的影响。

但是现在问题出现在我的代码中:

 public void CreateFlattenedMap() { var parentGroups = _nodeDependencies.GroupBy(d => d.ParentNodeId); var dictionary = parentGroups.ToDictionary(d => d, d => d.ToList()); ParentNodeAndRelatedChildrenFlattenedMap = dictionary; } 

好吧,它不喜欢我的字典分配,因为它是由ToDictionary()创建的>字典。 所以不知道如何将这个分组分组并且是一个字典,即List>其中字典中的Node是我正在分组的那个父节点的Node实例(是的,我正在对它的Node.ParentId进行分组但是我想要尽管在最后的ToDictionary中节点,而List>是来自Parent Node.Children属性的子节点列表。

这是一个更完整的实现看起来像:

 public class TreeNode { private T _item; private TreeNode _parentNode; private List> _children; public TreeNode(T item) { _item = item; } public void SetParentNode(T parent) { _parentNode.Item = parent; } public T Item { get { return _item; } set { _item = value; } } public void AddChild(T child) { _children.Add(new TreeNode(child)); } public void RemoveChild(T child) { var node = _children.FirstOrDefault(e => e.Item.Equals(child)); if (node != null) _children.Remove(node); } } 

还有你的问题:

构造函数如何看待并根据用法创建此类?

正如您在上面的AddChild()看到的,只需指定构造函数的子类型即可。

 var node = new TreeNode(item); 

所以如果我有这样的东西, T如何被使用以及我从中获益?

使用generics可以在完成正确的时候重写代码。 在上面的实现中,我们可以通过简单地改变T来创建基本上我们想要的任何类型的树结构。 因此,如果我们需要多种类型的树结构,这可以节省我们很多时间。

 var intTreeNode = new TreeNode(10); var stringTreeNode = new TreeNode("hello world"); 

一般来说,在点击之前确实需要一些曝光时间,而你“只是得到它”,坚持下去。

构建树

要从可能有或可能没有父类别的类别列表构造树,您需要以某种方式遍历列表。 一个体面的方法是首先将它们组织成基于ParentCategoryID分组并构建树。 像这样(未经测试):

 public List> ConstructCategories(List categories) { var groups = categories.GroupBy(e => e.ParentCategoryID); var rootGroup = groups.Single(e => e.Key == null); var categories = List>(); foreach (var category in rootGroup) { // Create and fill category var node = new TreeNode(category); ConstructChildrenCategories(node, groups); categories.Add(node); } } public void ConstructChildrenCategories(TreeNode node, IEnumerable> groups) { var group = groups.Single(e => e.Key == node.Item.CategoryID); foreach (var category in group) { // Create and fill category var childNode = new TreeNode(category); ConstructChildrenCategories(childNode, groups); // We could do this automatically in both methods. childNode.SetParent(node.Item); node.AddChild(childNode); } } 

这可能会有所帮助:

 public interface ICategory { int Id { get; } int ParentId { get; } } public class Category : ICategory { int id; int parentId; public int Id { get { return id; }} public int ParentId { get { return parentId; }} } 

这是Node类:

 public class Node where T : ICategory { Node _parentNode; List> _children; public Node Parent { get { return _parentNode; }} public Node Child(int index) { return _children[index]; } public T Value; public Node(T value) { this.Value = value; } public void AddChild(T item) { Node child = new Node(item); this._children.Add(child); child._parentNode = this; } } 

这是Tree类:

 public class Tree where T : ICategory { List> values; public Tree() { this.values = new List>(); } public Node FindNode(int id) { if (values.Exists(input => input.Value.Id == id)) { return values.Find(input => input.Value.Id == id); } else { return null; } } public void AddNode(T value) { Node parent = FindNode(value.ParentId); if (parent != null) { parent.AddChild(value); } } } 

你无法完成树和treenode的所有function。

而是将类数据添加到Treenode。

例如

 class MyClass { public int A; public string B; } ... TreeNode Node = TreeView.Nodes.Add("AAA"); MyClass Data = new MyClass(); Node.Tag = Data; 

分配给TreeNode的数据不会被删除。 你也可以使用整个树属性和节点成员。

你应该做的唯一事情就是在使用节点数据时进行类型转换。

 TreeNode Node = TreeView.Nodes[0]; MyClass Temp = Node.Tag as MyClass;