# Tikz tree drawing with comments to each level

I have problem with drawing trees with tikz.

The tree is correct, but 'rightarrows' wrongly indicate to text, which is related to each tree-level (it doesn't look good). Of course, the text should by shown also without circles.

Could anyone can help with that?

I wrote the tree, based on this example: http://www.texample.net/tikz/examples/merge-sort-recursion-tree

My code:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{trees}

\begin{document}
\begin{tikzpicture}[level distance=1.5cm,
level 1/.style={sibling distance=3.5cm},
level 2/.style={sibling distance=1cm}]
\tikzstyle{every node}=[circle,draw]
\node [red] {1}
child [red] {
node {3}
child { node {4} }
child [black] { node {5} }
child [black] { node {5} }
}
child {
node {3}
child { node {4} }
child { node {5} }
child { node {5} }
}
child {
node {3}
child { node {4} }
child { node {5} }
child { node {5}
child [grow=right] { node (q) {$\Rightarrow$} edge from parent [draw=none]
child [grow=right] {node (q) {$\textrm{2nd level arrow indicates here}$} edge from parent[draw=none]
child [grow=up] {node (q) {$\Rightarrow$} edge from parent[draw=none]
child [grow=right] {node (r) {$\textrm{1st level arrow indicates here}$} edge from parent[draw=none]
child [grow=up] {node (s) {$\Rightarrow$} edge from parent[draw=none]
child [grow=right] {node (r) {$\textrm{1st level arrow indicates here}$} edge from parent[draw=none]
}
}
}
}
}
}
}
};

\end{tikzpicture}
\end{document}

-

You can make use of an interesting feature of TikZ tree nodes. If you give a name to the root node, eg. Root, then all the nodes in the tree are automatically named too. Each of the children of node Root are named Root-1, Root-2, Root-3 and so on. Each of these children can have childrens in turn, which are named with the same schema. For example, in your tree, the leftmost child node would be called Root-1-1, while the rightmost node of the tree is Root-3-3.

Once you know the names of these nodes, you can draw anything at coordinates relative to them. For example:

\path (Root)  ++(3cm,0) node{Foo};


Would place the text Foo at 3cm from the Root node.

If you want the comments to be vertically aligned, they should share the horizontal coordinate. A good reference point from which position each comment would be the coordinate whose y part is the same of the commented level, while the x part is the same than the rightmost node. These coordinates can be specified using -| syntax. For example, coordinate (Root -| Root-3-3) is the point at the intersection between a horizontal line through Root and a vertical line through Root-3-3. This is the point marked in red in the following picture:

In the same way (Root-1 -| Root-3-3) would give a point at the same horizontal coordinate, but at second level, and (Root-1-1 -| Root-3-3) for the third level.

These coordinates can be used to position the comments and the arrows, as the following MWE shows:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{trees}

\begin{document}
\begin{tikzpicture}[level distance=1.5cm,
level 1/.style={sibling distance=3.5cm},
level 2/.style={sibling distance=1cm}]
\tikzstyle{every node}=[circle,draw]
\node (Root) [red] {1}
child [red] {
node {3}
child { node {4} }
child [black] { node {5} }
child [black] { node {5} }
}
child {
node {3}
child { node {4} }
child { node {5} }
child { node {5} }
}
child {
node {3}
child { node {4} }
child { node {5} }
child { node {5} }
};
\begin{scope}[every node/.style={right}]
\path (Root    -| Root-3-3) ++(5mm,0) node {$\Rightarrow$} ++(5mm,0) node {1st level arrow indicates here};
\path (Root-1  -| Root-3-3) ++(5mm,0) node {$\Rightarrow$} ++(5mm,0) node {2nd level arrow indicates here};
\path (Root-1-1-| Root-3-3) ++(5mm,0) node {$\Rightarrow$} ++(5mm,0) node {3rd level arrow indicates here};
\end{scope}

\end{tikzpicture}
\end{document}


Wich results in:

Of course this kind of repetitive tasks are better handled with a loop. In this case I will use a variable called \text to loop over the comments for each level, and let the body of the loop to calculate the appropiate coordinates. I use a nasty trick, in which the string "-1" is added to the end of the macro \level at each iteration of the loop, so that the first iteration it expands to Root, the second one to Root-1, the third to Root-1-1 and so on:

 \begin{scope}[every node/.style={right}]
\xdef\level{Root}  % Initial top level
\def\rightmostnode{Root-3-3}   % Name of the node with greater x coordinate
\foreach \text in {1st level arrow indicates here,
2nd level arrow indicates here,
3rd level arrow indicates here}
{
\path (\level -|\rightmostnode) ++(5mm,0) node{$\Rightarrow$} ++(5mm,0) node {\text};
\xdef\level{\level-1}
}
\end{scope}


Note that this "general" solution produces the same result, but is more complex and uses more lines and memory than the initial, more straight, solution. But I could not help showing it. It is a programmer's disease.

-
Very good advice! – Paul Gaborit Jul 17 '12 at 22:26

You can use the technique described in this question How to draw custom nodes attached to tikz-qtree? to draw the annotations as a separate tree beside the first tree using TikZ's scope mechanism. This way you will line up the levels correctly. For most trees, the tikz-qtree package provides a much simpler syntax for entering the tree itself.

\documentclass{article}
\usepackage{tikz}
\usepackage{tikz-qtree}
\begin{document}

\begin{tikzpicture}[every tree node/.style={draw,circle},edge from parent path={(\tikzparentnode) -- (\tikzchildnode)},sibling distance=.5cm]
\Tree [.\node[red] (1) {1};
\edge[red]; [.\node[red] (3) {3}; \edge[red];[.\node[red] (4) {4}; ] [.5 ] [.5 ] ]
[.3 [.4 ] [.5 ] [.5 ] ]
[.3 [.4 ] [.5 ] [.5 ] ]
]
\begin{scope}[xshift=3in,every tree node/.style={},edge from parent path={}]
\Tree [.{First level} [.{Second Level} [.{Third level} ]]]
\end{scope}
\end{tikzpicture}
\end{document}


-
This works until you end up with multiline nodes or levels which are not equally spaced. I did the same thing with an entire set of seminars using qtree and it was a pita trying to get the manual spacing adjustments right. (I had stuff on the left of the tree, as well, and Beamer overlay specifications, so it all got very complicated.) – cfr Jun 26 '15 at 22:32

This is a demonstration of a package I'm working on which is supposed (theoretically) to make this kind of tree easier to draw. It is basically a forest style. The main package is prooftrees but it also will, I hope, include justtrees which is better suited to this case. (justtrees is simpler, basically.)

Here's an example. Should you be sufficiently brave to want to try this at home, ask me for an updated copy of the package. The previous version is on this site but doesn't include the justtree environment used here.

This environment has the following syntax:

\begin{justtree}
{<preamble>}
<tree specification>
\end{justtree}


The <premable> can be empty, but the argument is mandatory. If specified, it may include anything allowable in a forest preamble and may also specify various options specific to the justtrees package.

In this case, most of the tree's preamble is specifying TikZ/forest configuration. One notable deviation is the parent anchor=, which is resetting the parent nodes' anchors to forest's default. This is because justtrees sets the anchor to south which is not wanted here. (This is because prooftrees does the same. There it is typically wanted. I'm not sure whether justtrees should simply not do this....)

The arrow just style is specifying a wrapper for the just key provided by justtrees. This key sets the descriptors for each level on the right of the tree. The nodes here are aligned automatically by the package before the tree is drawn.

Anyway, it is all very dodgy...

Caveat emptor...

\documentclass[tikz, border=5pt]{standalone}
\usepackage{justtrees}% v0.03

\begin{document}
\begin{justtree}
{
for tree={
circle,
draw,
parent anchor=,
},
arrow just/.style={
just={$\Rightarrow$ #1},
},
colour me/.style={
draw=#1,
edge={draw=#1},
text=#1,
},
trail/.style={
colour me=#1,
for ancestors={colour me=#1},
}
}
[1, arrow just={1st level arrow indicates here}
[3, arrow just={2nd level arrow indicates here}
[4, arrow just={3rd level arrow indicates here}, trail=red]
[5]
[5]
]
[3
[4]
[5]
[5]
]
[3
[4]
[5]
[5]
]
]
\end{justtree}
\end{document}


-