The Problem

Visualizing data structures can be a great aid in debugging. Unfortunately most development environments don't have the capability to display linked data in graphical form. One notable exception is the GNU Data Display Debugger.

A Solution

In this four-part series, we will explore a few simple techniques for drawing data structures using the dot language.

  • Part 0: The dot Language.
  • Part 1: Some Advanced Features of the dot Language.
  • Part 2: Visualizing Data Structures in C.
  • Part 3: Visualizing Data Structures in Java.

dot is part of the popular graphviz suite of tools.

Basics of the dot Language

dot is used to draw graphs which have a (mostly) hierarchical structure. The language is easily understood by example. A binary tree might be specified as

digraph bintree {
  10 -> 5;
  10 -> 15;
  5  -> 2;
  5  -> 8;
  2  -> 1;
  2  -> 3;
  8  -> 6;
  8  -> 7;
  15 -> 13;
  15 -> 20;
}

Edges are given with: startNode -> endNode.

Use the dot command to render this to an SVG file

dot -Tsvg input.dot -ooutput.svg

The result can be viewed in your browser

the-dot-language-example0.png

dot can also handle general graph structures. Here is a non-hierarchical graph

digraph cycle {
  1 -> 2 -> 3 -> 4 -> 1;
}

the-dot-language-cycle.png

Care must be used if the ordering of children is important. Had the two children of node 8 been reversed in the source file as in

digraph bintree {
  10 -> 5;
  10 -> 15;
  5  -> 2;
  5  -> 8;
  2  -> 1;
  2  -> 3;
  8  -> 7;
  8  -> 6;
  15 -> 13;
  15 -> 20;
}

The result would not be a correctly rendered binary tree

the-dot-language-example1.png

To remedy this, set the ordering to match the order listed in the source file

digraph bintree {
  ordering=out;
  /* ... */
}

and list the children of each node from lowest to highest.

Node Shapes

The default shapes of nodes in dot are ellipses. Differently-shaped nodes can be drawn by writing the node name followed by the shape as indicated by the red lines

digraph bintree {
  ordering=out;
  1  [shape=rectangle];
  3  [shape=rectangle];
  6  [shape=rectangle];
  7  [shape=rectangle];
  13 [shape=rectangle];
  20 [shape=rectangle];
  10 -> 5;
  10 -> 15;
  5  -> 2;
  5  -> 8;
  2  -> 1;
  2  -> 3;
  8  -> 6;
  8  -> 7;
  15 -> 13;
  15 -> 20;
}

The tree now looks like

the-dot-language-example2.png

The location of the [shape = rectangle] lines in the source file is unimportant.

Colors

Nodes can be filled or outlined with a particular color. Let's outline the interior nodes in our tree brown and fill in the leaves light green. To do this, set the color attributes of each node. For outline colors write: color = brown. For color fills write: color = palegreen,style = filled. Let's color the edges in the tree brown as well. Colored edges should be followed with [color = brown]

digraph bintree {
  ordering=out;
  1        [shape=rectangle, color=palegreen, style=filled];
  3        [shape=rectangle, color=palegreen, style=filled];
  6        [shape=rectangle, color=palegreen, style=filled];
  7        [shape=rectangle, color=palegreen, style=filled];
  13       [shape=rectangle, color=palegreen, style=filled];
  20       [shape=rectangle, color=palegreen, style=filled];
  10       [color=brown];
  5        [color=brown];
  2        [color=brown];
  8        [color=brown];
  15       [color=brown];
  10 -> 5  [color=brown];
  10 -> 15 [color=brown];
  5  -> 2  [color=brown];
  5  -> 8  [color=brown];
  2  -> 1  [color=brown];
  2  -> 3  [color=brown];
  8  -> 6  [color=brown];
  8  -> 7  [color=brown];
  15 -> 13 [color=brown];
  15 -> 20 [color=brown];
}

the-dot-language-example3.png

Next

In the next part of this series, we will explore some more advanced features of dot:

  • Record structures with labeled fields.
  • Subgraphs.