Ahaha
Ahaha

Reputation: 426

traverse all leaf nodes in a tree C#

I am trying to traverse all leaf nodes in a tree using queue. But I cannot get any output.

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());
    }

}

A node can have any number of children. And here is what I wrote to print all leaf nodes out. I cannot get anything, I think only the last line Console.WriteLine(""); was executed, but I cannot figure out why.

    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("");

    }

Thanks for any help. The tree class is this, actually I cannot find my debug window anywhere... I only wrote the PrintSentence method, and other things was written by someone else.

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();
    }
}

Upvotes: 4

Views: 8852

Answers (3)

Rob Lans
Rob Lans

Reputation: 21

Generic solution:

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;
                }
            }
        }
    }
}

Usage:

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

Upvotes: 1

Tomas Kubes
Tomas Kubes

Reputation: 25108

Separate node traversal and traversal action like this:

I have choose recursion, because the deep of recusrion for trees is not usually problem and you don't need to much memory for 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;
               }
           } 
       }
   }
}

And separate traversal action:

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

Upvotes: 0

Ideae
Ideae

Reputation: 622

You'll need to replace this line

if (currentNode.Children == null)

with this

if (currentNode.Children.Count == 0)

This will check if the list has no elements (no children). Since you always initialize your list, it will won't be null to begin with, even when it is empty.

Upvotes: 3

Related Questions