How do I print out a tree structure?

Simon picture Simon · Oct 30, 2009 · Viewed 48.2k times · Source

I'm trying to improve performance in our app. I've got performance information in the form of a tree of calls, with the following node class:

public class Node
{
    public string Name; // method name
    public decimal Time; // time spent in method
    public List<Node> Children;
}

I want to print out the tree such that I can see lines between the nodes - something like in this question. What's an algorithm I can use in C# for doing that?

Edit: Obviously I need to use recursion - but my attempts keep putting the lines in the wrong places. What I'm asking for is a specific algorithm that will print the tree in a nice manner - the details of when to print a vertical line and when to print a horizontal one.

Edit: It isn't sufficient just to use copies of a string to indent the nodes. I'm not looking for

A
|-B
|-|-C
|-|-D
|-|-|-E
|-F
|-|-G

it has to be

A
+-B
| +-C
| +-D
|   +-E
+-F
  +-G

or anything similar, so long as the tree structure is visible. Notice that C and D are indented differently to G - I can't just use a repeated string to indent the nodes.

Answer

Will picture Will · Oct 30, 2009

The trick is to pass a string as the indent and to treat the last child specially:

class Node
{    
   public void PrintPretty(string indent, bool last)
   {
       Console.Write(indent);
       if (last)
       {
           Console.Write("\\-");
           indent += "  ";
       }
       else
       {
           Console.Write("|-");
           indent += "| ";
       }
       Console.WriteLine(Name);

       for (int i = 0; i < Children.Count; i++)
           Children[i].PrintPretty(indent, i == Children.Count - 1);
   }
}

If called like this:

root.PrintPretty("", true);

will output in this style:

\-root
  \-child
    |-child
    \-child
      |-child
      |-child
      \-child
        |-child
        |-child
        | |-child
        | \-child
        |   |-child
        |   |-child
        |   |-child
        |   \-child
        |     \-child
        |       \-child
        \-child
          |-child
          |-child
          |-child
          | \-child
          \-child
            \-child