2015-01-11 40 views
2

我正在尝试使用队列遍历树中的所有叶节点。 但我无法获得任何输出。遍历树中的所有叶节点C#

class MyNode<T> 
{ 
    public T Data { get; set; } 
    public MyNode<T> Parent { get; set; } 
    public List<MyNode<T>> Children = new List<MyNode<T>>(); 
    public MyNode(T data, MyNode<T> parent) 
    { 
     Data = data; 
     Parent = parent; 
    } 

    public override string ToString() 
    { 
     if (Children == null) return Data.ToString(); 
     return string.Format("{0} {1} ", Data.ToString(), Children.ToString()); 
    } 

} 

节点可以有任意数量的子节点。这是我写的打印所有叶节点的内容。我什么也得不到,我想只有最后一行Console.WriteLine(“”);被执行,但我不明白为什么。

public static void PrintSentence(MyNode<string> root) 
    { 
     if (root == null) // Return when the tree is empty. 
      return; 

     Queue<MyNode<string>> nodeQueue = new Queue<MyNode<string>>(); 
     nodeQueue.Enqueue(root); 

     MyNode<string> currentNode = root; 

     while (nodeQueue.Count != 0) 
     { 
      currentNode = nodeQueue.Peek(); 
      nodeQueue.Dequeue(); 

      if (currentNode.Children == null) // Print strings only when the current node is a leaf node. 
       Console.Write(currentNode.Data + " "); 

      for (int i = 0; i < currentNode.Children.Count(); i++) 
       nodeQueue.Enqueue(currentNode.Children[i]); 
     } 

     Console.WriteLine(""); 

    } 

感谢您的任何帮助。 树类是这样的,实际上我无法在任何地方找到我的调试窗口... 我只写了PrintSentence方法,其他的东西是其他人写的。

class Tree<T> 
{ 
    public MyNode<T> Root { get; set; } 
    public Tree(MyNode<T> root) { Root = root; } 
    public override string ToString() 
    { 
     if (Root == null) return ""; 
     return Root.ToString(); 
    } 
} 
+0

能否请您提供更多的信息 - 尤其是你的树?另外,当你在调试器中执行代码时,会执行哪些代码,哪些不执行? –

回答

3

你需要替换此行

if (currentNode.Children == null)

与此

if (currentNode.Children.Count == 0)

这将检查列表没有任何元素(没有孩子)。既然你总是初始化你的列表,它将不会为空,即使它是空的。

+0

我懂了!非常感谢! – Ahaha

+1

请注意,“它永远不会为空”不是真的,因为OP会将该列表公开,并且可以很容易地将其设置为null。很好的回答将包括避免这种情况的建议(即通过不公开列表并且为'IEnumerable '添加r/o属性来读取儿童列表+方法添加/设置儿童)。 –

0

单独的节点遍历和遍历操作是这样的:

我有选择递归,因为树深recusrion通常不是问题,你不需要太多内存queueu。

public static class MyNodeExt<T> 
{ 
    IEnumerable<T> TraverseLeafs<T>(this MyNode<T> node) 
    { 
     if (node.Children.Count == 0) 
      yield return node; 
     else 
     { 
      foreach(var child in root.Children) 
      { 
       foreach(var subchild in child.TraverseLeafs()) 
       { 
        yield return subchild; 
       } 
      } 
     } 
    } 
} 

和独立遍历操作:

public static void PrintSentence(MyNode<string> root) 
{ 
    foreach(var node in root.TraverseLeafs()) 
    { 
     Console.Write(node .Data + " "); 
    }  
} 
0

通用的解决方案:

public static class Hierarchy 
{ 
    /// <summary> 
    /// Gets the collection of leafs (items that have no children) from a hierarchical collection 
    /// </summary> 
    /// <typeparam name="T">The collection type</typeparam> 
    /// <param name="source">The sourceitem of the collection</param> 
    /// <param name="getChildren">A method that returns the children of an item</param> 
    /// <returns>The collection of leafs</returns> 
    public static IEnumerable<T> GetLeafs<T>(T source, Func<T, IEnumerable<T>> getChildren) 
    { 
     if (!getChildren(source).Any()) 
     { 
      yield return source; 
     } 
     else 
     { 
      foreach (var child in getChildren(source)) 
      { 
       foreach (var subchild in GetLeafs(child, getChildren)) 
       { 
        yield return subchild; 
       } 
      } 
     } 
    } 
} 

用法:

var leafs = Hierarchy.GetLeafs(root, (element) => element.Children);