Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.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语言中的树型数据结构#_C#_Data Structures - Fatal编程技术网

C# C语言中的树型数据结构#

C# C语言中的树型数据结构#,c#,data-structures,C#,Data Structures,我在寻找C#中的树或图形数据结构,但我想没有提供。解释一下原因。是否有一个常用的方便的库来提供此功能?也许可以通过一种策略模式来解决文章中提出的问题 我觉得实现自己的树有点傻,就像实现自己的ArrayList一样 我只想要一个通用的树,它可以是不平衡的。想象一下目录树。C5看起来很漂亮,但它们的树结构似乎实现为更适合搜索的平衡红黑树,而不是表示节点层次结构 一般优秀的数据库有几种不同的基于树的数据结构,包括集合、包和字典。如果您想研究它们的实现细节,可以使用源代码。(我在生产代码中使用了C5集合

我在寻找C#中的树或图形数据结构,但我想没有提供。解释一下原因。是否有一个常用的方便的库来提供此功能?也许可以通过一种策略模式来解决文章中提出的问题

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


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

一般优秀的数据库有几种不同的基于树的数据结构,包括集合、包和字典。如果您想研究它们的实现细节,可以使用源代码。(我在生产代码中使用了C5集合,效果很好,尽管我没有专门使用任何树结构。)

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

您需要实现的基本结构将是一个节点集合,下面是一些开始的选项。让我们假设类节点是整个解决方案的基类

如果只需要沿树向下导航,则节点类需要子类的列表

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


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

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

斯科特·米切尔(Scott Mitchell)

代表void TreeVisitor(T nodeData);
delegate void TreeVisitor<T>(T nodeData);

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

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

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

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

    public void Traverse(NTree<T> node, TreeVisitor<T> visitor)
    {
        visitor(node.data);
        foreach (NTree<T> kid in node.children)
            Traverse(kid, visitor);
    }
}
类NTree { 私有T数据; 私人关系人子女; 公共NTree(T数据) { 这个数据=数据; children=newlinkedlist(); } 公共void AddChild(T数据) { AddFirst(新NTree(数据)); } 公共NTree GetChild(int i) { foreach(儿童中的NTree n) 如果(--i==0) 返回n; 返回null; } 公共无效遍历(NTree节点、TreeVisitor访问者) { 访问者(node.data); foreach(node.childs中的NTree kid) 特拉弗斯(孩子、访客); } }
简单的递归实现。。。 <40行代码。。。 您只需要在类之外保留对树的根的引用, 或者将其包装到另一个类中,或者重命名为TreeNode???

请参见


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

我的观点是,这与我的非常相似,只是有点传统。就我而言,我没有在
List
中遇到任何性能问题。如果需要的话,切换到LinkedList是很容易的


namespace Overby.Collections
{
公共级树节点
{
私有只读T_值;
私有只读列表_children=new List();
公共树节点(T值)
{
_价值=价值;
}
公共树节点本[int i]
{
获取{return_children[i];}
}
公共树节点父{get;private set;}
公共T值{get{return_值;}}
公共只读集合子项
{
获取{return _children.AsReadOnly();}
}
公共树节点AddChild(T值)
{
var node=newtreenode(value){Parent=this};
_添加(节点);
返回节点;
}
公共树节点[]添加子节点(参数T[]值)
{
返回值。选择(AddChild.ToArray();
}
公共bool RemoveChild(TreeNode节点)
{
return _children.Remove(节点);
}
公共无效遍历(操作)
{
作用(价值);
foreach(var child in_children)
遍历(动作);
}
公共IEnumerable展平()
{
返回新的[]{Value}.Concat(_children.SelectMany(x=>x.flatte());
}
}
}

如果需要使用更少内存的根目录树数据结构实现,可以按如下方式编写节点类(C++实现):


我对解决方案有一点扩展

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

注意,它不同于非泛型实现,您不需要在“NodeWorker”中强制转换“node”

下面是我的例子:

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

  protected List<T> children;

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

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

  public void Traverse(Action<int, T> visitor)
  {
    this.traverse(0, visitor);
  }

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

public class GenericTreeNext : GenericTree<GenericTreeNext> // 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);  
}  
公共类GenericTree,其中T:GenericTree//递归约束
{
//没有特定的数据声明
受保护儿童名单;
公共GenericTree()
{
this.children=新列表();
}
公共虚拟void AddChild(T newChild)
{
this.children.Add(newChild);
}
公共无效遍历(操作访问者)
{
遍历(0,访问者);
}
受保护的虚拟空遍历(整数深度,操作访问者)
{
访客(深度,(T)本);
对于
class Node {
       Node* parent;
       int item; // depending on your needs

       Node* firstChild; //pointer to left most child of node
       Node* nextSibling; //pointer to the sibling to the right
}
public class GenericTree<T> where T : GenericTree<T> // recursive constraint  
{
  // no specific data declaration  

  protected List<T> children;

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

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

  public void Traverse(Action<int, T> visitor)
  {
    this.traverse(0, visitor);
  }

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

public class GenericTreeNext : GenericTree<GenericTreeNext> // 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);  
}  
public class TreeNode<TValue>
{
    #region Properties
    public TValue Value { get; set; }
    public List<TreeNode<TValue>> Children { get; private set; }
    public bool HasChild { get { return Children.Any(); } }
    #endregion
    #region Constructor
    public TreeNode()
    {
        this.Children = new List<TreeNode<TValue>>();
    }
    public TreeNode(TValue value)
        : this()
    {
        this.Value = value;
    }
    #endregion
    #region Methods
    public void AddChild(TreeNode<TValue> treeNode)
    {
        Children.Add(treeNode);
    }
    public void AddChild(TValue value)
    {
        var treeNode = new TreeNode<TValue>(value);
        AddChild(treeNode);
    }
    #endregion
}
public class TreeNode<T> : IEnumerable<TreeNode<T>>
{

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

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

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

    ... // for iterator details see below link
}
TreeNode<string> root = new TreeNode<string>("root");
{
    TreeNode<string> node0 = root.AddChild("node0");
    TreeNode<string> node1 = root.AddChild("node1");
    TreeNode<string> node2 = root.AddChild("node2");
    {
        TreeNode<string> node20 = node2.AddChild(null);
        TreeNode<string> node21 = node2.AddChild("node21");
        {
            TreeNode<string> node210 = node21.AddChild("node210");
            TreeNode<string> node211 = node21.AddChild("node211");
        }
    }
    TreeNode<string> node3 = root.AddChild("node3");
    {
        TreeNode<string> node30 = node3.AddChild("node30");
    }
}
class BST
{
    public class Node
    {
        public Node Left { get; set; }
        public object Data { get; set; }
        public Node Right { get; set; }

        public Node()
        {
            Data = null;
        }

        public Node(int Data)
        {
            this.Data = (object)Data;
        }

        public void Insert(int Data)
        {
            if (this.Data == null)
            {
                this.Data = (object)Data;
                return;
            }
            if (Data > (int)this.Data)
            {
                if (this.Right == null)
                {
                    this.Right = new Node(Data);
                }
                else
                {
                    this.Right.Insert(Data);
                }
            }
            if (Data <= (int)this.Data)
            {
                if (this.Left == null)
                {
                    this.Left = new Node(Data);
                }
                else
                {
                    this.Left.Insert(Data);
                }
            }
        }

        public void TraverseInOrder()
        {
            if(this.Left != null)
                this.Left.TraverseInOrder();
            Console.Write("{0} ", this.Data);
            if (this.Right != null)
                this.Right.TraverseInOrder();
        }
    }

    public Node Root { get; set; }
    public BST()
    {
        Root = new Node();
    }
}
  public class TreeNode<T> : IEnumerable<TreeNode<T>>
    {

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

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

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

        public IEnumerator<TreeNode<T>> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return (IEnumerator)GetEnumerator();
        }
    }
    public class TreeNodeEnum<T> : IEnumerator<TreeNode<T>>
    {

        int position = -1;
        public List<TreeNode<T>> Nodes { get; set; }

        public TreeNode<T> Current
        {
            get
            {
                try
                {
                    return Nodes[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }


        object IEnumerator.Current
        {
            get
            {
                return Current;
            }
        }


        public TreeNodeEnum(List<TreeNode<T>> nodes)
        {
            Nodes = nodes;
        }

        public void Dispose()
        {
        }

        public bool MoveNext()
        {
            position++;
            return (position < Nodes.Count);
        }

        public void Reset()
        {
            position = -1;
        }
    }
    public class NTree<T>
    {
        public T data;
        public LinkedList<NTree<T>> children;

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

        public void AddChild(T data)
        {
            var node = new NTree<T>(data) { Parent = this };
            children.AddFirst(node);
        }

        public NTree<T> Parent { get; private set; }

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

        public void Traverse(NTree<T> node, TreeVisitor<T> visitor, string t, ref NTree<T> r)
        {
            visitor(node.data, node, t, ref r);
            foreach (NTree<T> kid in node.children)
                Traverse(kid, visitor, t, ref r);
        }
    }
    public static void DelegateMethod(KeyValuePair<string, string> data, NTree<KeyValuePair<string, string>> node, string t, ref NTree<KeyValuePair<string, string>> r)
    {
        string a = string.Empty;
        if (node.data.Key == t)
        {
            r = node;
            return;
        }
    }
 NTree<KeyValuePair<string, string>> ret = null;
 tree.Traverse(tree, DelegateMethod, node["categoryId"].InnerText, ref ret);
class Program
{
    static void Main(string[] args)
    {
        var tree = new Tree<string>()
            .Begin("Fastfood")
                .Begin("Pizza")
                    .Add("Margherita")
                    .Add("Marinara")
                .End()
                .Begin("Burger")
                    .Add("Cheese burger")
                    .Add("Chili burger")
                    .Add("Rice burger")
                .End()
            .End();

        tree.Nodes.ForEach(p => PrintNode(p, 0));
        Console.ReadKey();
    }

    static void PrintNode<T>(TreeNode<T> node, int level)
    {
        Console.WriteLine("{0}{1}", new string(' ', level * 3), node.Value);
        level++;
        node.Children.ForEach(p => PrintNode(p, level));
    }
}

public class Tree<T>
{
    private Stack<TreeNode<T>> m_Stack = new Stack<TreeNode<T>>();

    public List<TreeNode<T>> Nodes { get; } = new List<TreeNode<T>>();

    public Tree<T> Begin(T val)
    {
        if (m_Stack.Count == 0)
        {
            var node = new TreeNode<T>(val, null);
            Nodes.Add(node);
            m_Stack.Push(node);
        }
        else
        {
            var node = m_Stack.Peek().Add(val);
            m_Stack.Push(node);
        }

        return this;
    }

    public Tree<T> Add(T val)
    {
        m_Stack.Peek().Add(val);
        return this;
    }

    public Tree<T> End()
    {
        m_Stack.Pop();
        return this;
    }
}

public class TreeNode<T>
{
    public T Value { get; }
    public TreeNode<T> Parent { get; }
    public List<TreeNode<T>> Children { get; }

    public TreeNode(T val, TreeNode<T> parent)
    {
        Value = val;
        Parent = parent;
        Children = new List<TreeNode<T>>();
    }

    public TreeNode<T> Add(T val)
    {
        var node = new TreeNode<T>(val, this);
        Children.Add(node);
        return node;
    }
}
Fastfood
   Pizza
      Margherita
      Marinara
   Burger
      Cheese burger
      Chili burger
      Rice burger