C# 使用队列的深度优先搜索

C# 使用队列的深度优先搜索,c#,.net-3.5,tree,depth-first-search,tree-traversal,C#,.net 3.5,Tree,Depth First Search,Tree Traversal,如何使用c#中的队列进行深度优先搜索 以下是我的数据结构: public class Node { public string Name{get;set} public IEnumerable<Node> Children{get;set;} } 公共类节点 { 公共字符串名称{get;set} 公共IEnumerable子项{get;set;} } 现在我有了一个节点对象的集合,每个节点对象都有子节点,它也有子节点,以此类推 我想访问每个节点并将其转换为不同的形式 如下

如何使用c#中的队列进行深度优先搜索

以下是我的数据结构:

public class Node
{
  public string Name{get;set}
  public IEnumerable<Node> Children{get;set;}
}
公共类节点
{
公共字符串名称{get;set}
公共IEnumerable子项{get;set;}
}
现在我有了一个节点对象的集合,每个节点对象都有子节点,它也有子节点,以此类推

我想访问每个节点并将其转换为不同的形式

如下所示:

public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes)
        {
            var queue = new Queue<Node>(nodes);

            while (queue.Any())
            {
                var next = queue.Dequeue();
                yield return BuildContentFromSingle(next);

                foreach (var child in next.Children)
                {
                    queue.Enqueue(child);
                }
            }
        }

        public IContent BuildContentFromSingle(Node node)
        {
            var content = _contentFactory.Create(node);
            return content;
        }  
public IEnumerable BuildContentFrom(IEnumerable节点)
{
var queue=新队列(节点);
while(queue.Any())
{
var next=queue.Dequeue();
从Single(下一个)返回BuildContentFromSingle;
foreach(next.Children中的var child)
{
排队。排队(子级);
}
}
}
公共IContent BuildContentFromSingle(节点)
{
var content=\u contentFactory.Create(节点);
返回内容;
}  

由于某些原因,上面的内容并没有给我深度优先。您能帮忙吗?

深度优先搜索是使用后进先出数据结构实现的,因此您需要将
队列
交换为一个队列。使用一个类似队列的FIFO结构给您代替。

< P>作为替代,您可以考虑使用递归来扁平化结构。这里有一个二叉树的例子。它演示了深度优先展平遍历

using System;
using System.Collections.Generic;

namespace Demo
{
    public static class Program
    {
        static void Main(string[] args)
        {
            var tree = buildTree(5, true);
            printTree1(tree);
            Console.WriteLine("---------------------------------------------");
            printTree2(tree);
        }

        // Print tree using direct recursion.

        static void printTree1<T>(Node<T> tree)
        {
            if (tree != null)
            {
                Console.WriteLine(tree.Value);
                printTree1(tree.Left);
                printTree1(tree.Right);
            }
        }

        // Print tree using flattened tree.

        static void printTree2<T>(Node<T> tree)
        {
            foreach (var value in flatten(tree))
            {
                Console.WriteLine(value);
            }
        }

        // Flatten tree using recursion.

        static IEnumerable<T> flatten<T>(Node<T> root)
        {
            if (root == null)
            {
                yield break;
            }

            foreach (var node in flatten(root.Left))
            {
                yield return node;
            }

            foreach (var node in flatten(root.Right))
            {
                yield return node;
            }

            yield return root.Value;
        }

        static Node<string> buildTree(int depth, bool left)
        {
            if (depth > 0)
            {
                --depth;
                return new Node<string>(buildTree(depth, true), buildTree(depth, false), "Node." + depth + (left ? ".L" : ".R"));
            }
            else
            {
                return new Node<string>(null, null, "Leaf." + (left ? "L" : "R"));
            }
        }
    }

    public sealed class Node<T>
    {
        public Node(Node<T> left, Node<T> right, T value)
        {
            _left  = left;
            _right = right;
            _value = value;
        }

        public Node<T> Left  { get { return _left;  } }
        public Node<T> Right { get { return _right; } }
        public T       Value { get { return _value; } }

        private readonly Node<T> _left;
        private readonly Node<T> _right;
        private readonly T       _value;
    }
}
使用系统;
使用System.Collections.Generic;
名称空间演示
{
公共静态类程序
{
静态void Main(字符串[]参数)
{
var-tree=buildTree(5,true);
printTree1(树);
Console.WriteLine(“-------------------------------------------------------------”;
printTree2(树);
}
//使用直接递归打印树。
静态void printTree1(节点树)
{
如果(树!=null)
{
Console.WriteLine(tree.Value);
printTree1(树左);
printTree1(树右);
}
}
//使用展平树打印树。
静态void printTree2(节点树)
{
foreach(展平(树)中的var值)
{
控制台写入线(值);
}
}
//使用递归展平树。
静态IEnumerable展平(节点根)
{
if(root==null)
{
屈服断裂;
}
foreach(展平中的var节点(root.Left))
{
收益回报节点;
}
foreach(展平中的var节点(根,右))
{
收益回报节点;
}
收益率返回根值;
}
静态节点构建树(int-depth,bool-left)
{
如果(深度>0)
{
--深度;
返回新节点(buildTree(depth,true),buildTree(depth,false),“Node.+depth+(left?”.L:“.R”);
}
其他的
{
返回新节点(null,null,Leaf.+(左?:“L”);
}
}
}
公共密封类节点
{
公共节点(节点左、节点右、T值)
{
_左=左;
_右=右;
_价值=价值;
}
公共节点左{get{return\u Left;}
公共节点权限{get{return\u Right;}}
公共T值{get{return_值;}}
私有只读节点_左;
私有只读节点_right;
私有只读T_值;
}
}
对于您的具体示例,我认为(无需测试)您可以这样做:

public static IEnumerable<Node> Flatten(Node root)
{
    foreach (var node in root.Children)
    {
        foreach (var child in Flatten(node))
        {
            yield return child;
        }
    }

    yield return root;
}
公共静态IEnumerable展平(节点根)
{
foreach(root.Children中的var节点)
{
foreach(展平中的变量子节点(节点))
{
退换子女;
}
}
产量回归根;
}
根据是否允许空节点,可能需要添加一些空检查:

public static IEnumerable<Node> Flatten(Node root)
{
    if (root != null)
    {
        foreach (var node in root.Children)
        {
            foreach (var child in Flatten(node))
            {
                if (child != null)
                {
                    yield return child;
                }
            }
        }

        yield return root;
    }
}
公共静态IEnumerable展平(节点根)
{
if(root!=null)
{
foreach(root.Children中的var节点)
{
foreach(展平中的变量子节点(节点))
{
if(child!=null)
{
退换子女;
}
}
}
产量回归根;
}
}

您可以递归地执行此操作

public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes) {
     foreach(var node in nodes){
         yield node;
         foreach(var c in BuildContentFrom(node.children)){
             yield c;
         }
     }
}
public IEnumerable BuildContentFrom(IEnumerable节点){
foreach(节点中的var节点){
屈服点;
foreach(BuildContentFrom(node.children)中的var c){
产量c;
}
}
}
当n较大和/或树较深时,这可能成为n-树的问题。 在这种情况下,您可以使用累加器

public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes) {
     if(!nodes.Any()) return Enumerable.Empty<IContent>();
     var acc = new List<IContent>();
     BuildContentFrom(nodes);
}

public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes, 
                                              IList<IContent> acc) {
     foreach(var node in nodes){
         acc.Add(BuildContentFromSingle(node));
         if(node.children.Any()) BuildContentFrom(node.children, acc);
     }
}
public IEnumerable BuildContentFrom(IEnumerable节点){
如果(!nodes.Any())返回Enumerable.Empty();
var acc=新列表();
BuildContentFrom(节点);
}
公共IEnumerable BuildContentFrom(IEnumerable节点,
IList(行政协调会){
foreach(节点中的var节点){
acc.Add(BuildContentFromSingle(node));
if(node.children.Any())BuildContentFrom(node.children,acc);
}
}
现在它是尾部递归的,如果编译器为此进行了优化(据我记忆中的C#设置),那么即使使用大型树,也不会出现堆栈问题

或者,您可以使用堆栈来收集仍然需要执行的工作

public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes)
{
    var stack= new Stack<Node>(nodes);

    while (stack.Any())
    {
        var next = stack.Pop();
        yield return BuildContentFromSingle(next);

        foreach (var child in next.Children)
        {
            stack.push(child);
        }
    }
}
public IEnumerable BuildContentFrom(IEnumerable节点)
{
var stack=新堆栈(节点);
while(stack.Any())
{
var next=stack.Pop();
从Single(下一个)返回BuildContentFromSingle;
foreach(next.Children中的var child)
{
栈.推(子);
}
}
}