当前位置:  开发笔记 > 编程语言 > 正文

C#中的树数据结构

如何解决《C#中的树数据结构》经验,为你挑选了8个好方法。

我在C#中寻找树或图形数据结构,但我想没有提供.对数据结构的广泛检查使用C#2.0解释了一些原因.是否有一个方便的库,通常用于提供此功能?也许通过策略模式来解决文章中提出的问题.

我觉得实现自己的树有点傻,就像我实现自己的ArrayList一样.

我只想要一个可以不平衡的通用树.想一下目录树.C5看起来很漂亮,但它们的树结构似乎被实现为更适合搜索的平衡红黑树而不是表示节点的层次结构.



1> David Boike..:

我最好的建议是没有标准的树数据结构,因为有很多方法可以实现它,用一个解决方案覆盖所有基础是不可能的.解决方案越具体,它就越不可能适用于任何给定的问题.我甚至对LinkedList感到恼火 - 如果我想要一个循环链表怎么办?

您需要实现的基本结构将是一组节点,这里有一些选项可以帮助您入门.我们假设类Node是整个解决方案的基类.

如果只需要向下导航树,那么Node类需要一个子列表.

如果需要向上导航树,则Node类需要指向其父节点的链接.

构建一个AddChild方法,负责处理这两点的所有细节以及必须实现的任何其他业务逻辑(子限制,对子项进行排序等)


@jk我相信SortedDictionary和SortedSet是在红/黑树上构建的,所以使用它们应该可行.
我个人不介意将某种自平衡二进制树添加到库中,因为这是一些额外的工作,而不仅仅是使用adjaceny列表.

2> Aaron Gage..:
delegate void TreeVisitor(T nodeData);

class NTree
{
    private T data;
    private LinkedList> children;

    public NTree(T data)
    {
         this.data = data;
        children = new LinkedList>();
    }

    public void AddChild(T data)
    {
        children.AddFirst(new NTree(data));
    }

    public NTree GetChild(int i)
    {
        foreach (NTree n in children)
            if (--i == 0)
                return n;
        return null;
    }

    public void Traverse(NTree node, TreeVisitor visitor)
    {
        visitor(node.data);
        foreach (NTree kid in node.children)
            Traverse(kid, visitor);
    }
}

简单的递归实现...... <40行代码...你只需要保持对类外部树的根的引用,或者将它包装在另一个类中,也许重命名为TreeNode?


在这种情况下,无论如何,在C#中,您可以避免编写自己的委托并使用预先制作的`Action `delegate:`public void traverse(NTree node,Action visitor)`.Action <>的签名是:`void Action (T obj)`.还有0到4个不同参数的版本.还有一个名为`Func <>`的函数的类似委托.
使addChild()返回它添加的NTree会使它更好地向树中添加数据.(除非我错过了使用它构建树的巧妙方法,而不依赖于新添加的子项== getChild(1)的实现细节?)
将遍历方法更改为静态或可能将其包装为隐藏递归性质是个好主意,但遍历很简单:创建一个带有委托签名的方法,即对于一个int的树:void my_visitor_impl(int datum) - 如果需要,将其设为静态,实例化delgate:TreeVisitor my_visitor = my_visitor_impl; 如果你使它静态,则在根节点或NTree类上调用:NTree .traverse(my_tree,my_visitor)
我怎么称呼这个代表?

3> Ronnie Overb..:

在我看来,这是我的,与Aaron Gage非常相似,只是更传统一点.出于我的目的,我没有遇到任何性能问题List.如果需要,可以很容易地切换到LinkedList.


namespace Overby.Collections
{
    public class TreeNode
    {
        private readonly T _value;
        private readonly List> _children = new List>();

        public TreeNode(T value)
        {
            _value = value;
        }

        public TreeNode this[int i]
        {
            get { return _children[i]; }
        }

        public TreeNode Parent { get; private set; }

        public T Value { get { return _value; } }

        public ReadOnlyCollection> Children
        {
            get { return _children.AsReadOnly(); }
        }

        public TreeNode AddChild(T value)
        {
            var node = new TreeNode(value) {Parent = this};
            _children.Add(node);
            return node;
        }

        public TreeNode[] AddChildren(params T[] values)
        {
            return values.Select(AddChild).ToArray();
        }

        public bool RemoveChild(TreeNode node)
        {
            return _children.Remove(node);
        }

        public void Traverse(Action action)
        {
            action(Value);
            foreach (var child in _children)
                child.Traverse(action);
        }

        public IEnumerable Flatten()
        {
            return new[] {Value}.Concat(_children.SelectMany(x => x.Flatten()));
        }
    }
}


我喜欢这个解决方案.我还发现我需要插入,我添加了以下方法来做到这一点.`public TreeNode InsertChild(TreeNode parent,T value){var node = new TreeNode (value){Parent = parent}; parent._children.Add(节点); 返回节点; ``var five = myTree.AddChild(5); myTree.InsertChild(five,55);`

4> Grzegorz Dev..:

另一种树形结构:

public class TreeNode : IEnumerable>
{

    public T Data { get; set; }
    public TreeNode Parent { get; set; }
    public ICollection> Children { get; set; }

    public TreeNode(T data)
    {
        this.Data = data;
        this.Children = new LinkedList>();
    }

    public TreeNode AddChild(T child)
    {
        TreeNode childNode = new TreeNode(child) { Parent = this };
        this.Children.Add(childNode);
        return childNode;
    }

    ... // for iterator details see below link
}

样品用法:

TreeNode root = new TreeNode("root");
{
    TreeNode node0 = root.AddChild("node0");
    TreeNode node1 = root.AddChild("node1");
    TreeNode node2 = root.AddChild("node2");
    {
        TreeNode node20 = node2.AddChild(null);
        TreeNode node21 = node2.AddChild("node21");
        {
            TreeNode node210 = node21.AddChild("node210");
            TreeNode node211 = node21.AddChild("node211");
        }
    }
    TreeNode node3 = root.AddChild("node3");
    {
        TreeNode node30 = node3.AddChild("node30");
    }
}

奖金
见完全成熟的树:

迭代器

搜索

的Java/C#

https://github.com/gt4dev/yet-another-tree-structure


-1?这棵树很完美,很好用:]

5> McKenzieG1..:

通常优秀的C5通用集合库有几种不同的基于树的数据结构,包括集合,包和字典.如果您想研究其实现细节,可以使用源代码.(我在生产代码中使用了C5集合,但是我没有特别使用任何树结构.)


不知道是否有些事情发生了变化,但现在这本书可以免费从C5网站下载为PDF.
缺乏文档不再是一个问题,因为有一个272页长的pdf补充库...不能评论代码质量,但从文档质量判断,我真的很期待今晚深入研究这个!
据我了解,这个C5库根本没有树,只有一些树派生的数据结构。

6> nietras..:

见http://quickgraph.codeplex.com/

QuickGraph为.Net 2.0及更高版本提供通用的定向/无向图形数据结构和算法.QuickGraph带有深度优先搜索,呼吸优先搜索,A*搜索,最短路径,k最短路径,最大流量,最小生成树,最少共同祖先等算法... QuickGraph支持MSAGL,GLEE和Graphviz渲染图形,序列化为GraphML等...



7> user7116..:

如果您想自己编写,可以从这个由六部分组成的文档开始,详细介绍C#2.0数据结构的有效使用以及如何分析C#中数据结构的实现.每篇文章都有示例和安装程序,其中包含您可以使用的示例.

Scott Mitchell撰写的"使用C#2.0对数据结构进行了广泛的检查"



8> Erik Nagel..:

我对解决方案有一点延伸.

使用递归泛型声明和派生子类,您可以更好地专注于您的实际目标.

请注意,它与非泛型实现不同,您不需要在'NodeWorker'中强制转换'node'.

这是我的例子:

public class GenericTree where T : GenericTree // recursive constraint  
{
  // no specific data declaration  

  protected List children;

  public GenericTree()
  {
    this.children = new List();
  }

  public virtual void AddChild(T newChild)
  {
    this.children.Add(newChild);
  }

  public void Traverse(Action visitor)
  {
    this.traverse(0, visitor);
  }

  protected virtual void traverse(int depth, Action visitor)
  {
    visitor(depth, (T)this);
    foreach (T child in this.children)
      child.traverse(depth + 1, visitor);
  }
}

public class GenericTreeNext : GenericTree // concrete derivation
{
  public string Name {get; set;} // user-data example

  public GenericTreeNext(string name)
  {
    this.Name = name;
  }
}

static void Main(string[] args)  
{  
  GenericTreeNext tree = new GenericTreeNext("Main-Harry");  
  tree.AddChild(new GenericTreeNext("Main-Sub-Willy"));  
  GenericTreeNext inter = new GenericTreeNext("Main-Inter-Willy");  
  inter.AddChild(new GenericTreeNext("Inter-Sub-Tom"));  
  inter.AddChild(new GenericTreeNext("Inter-Sub-Magda"));  
  tree.AddChild(inter);  
  tree.AddChild(new GenericTreeNext("Main-Sub-Chantal"));  
  tree.Traverse(NodeWorker);  
}  

static void NodeWorker(int depth, GenericTreeNext node)  
{                                // a little one-line string-concatenation (n-times)
  Console.WriteLine("{0}{1}: {2}", String.Join("   ", new string[depth + 1]), depth, node.Name);  
}  

推荐阅读
手机用户2402852387
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有