2015-01-11 2 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.Count == 0)

이 함께이 라인을

if (currentNode.Children == null)

를 교체해야합니다. 항상 목록을 초기화하므로 목록이 비어 있더라도 시작할 수 없습니다. 이 같은

+0

나는 그것을 얻었다! 정말 고맙습니다! – Ahaha

+1

OP는 공개 필드로 그 목록을 노출하고 쉽게 'null'로 설정 될 수 있기 때문에 "절대 null이 아님"은 사실이 아닙니다. 위의 경우를 피하기위한 권장 사항 (예 : List를 표시하지 않고 '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); 
관련 문제