C# 使用队列的深度优先搜索
如何使用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;} } 现在我有了一个节点对象的集合,每个节点对象都有子节点,它也有子节点,以此类推 我想访问每个节点并将其转换为不同的形式 如下
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)
{
栈.推(子);
}
}
}