2015-01-11 4 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

Обратите внимание, что «он никогда не будет null» на самом деле не так, потому что OP предоставляет этот список как общедоступное поле, и его можно легко установить на «null». Большой ответ будет включать рекомендацию избегать таких случаев (т. Е. Не выставлять список и вместо этого добавлять свойство r/o для 'IEnumerable ' для чтения списка children + метод add/set children). –

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

Generic решение:

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); 
Смежные вопросы