12

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

4 Answers 4

15

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:

Coordinate

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} }
        };
   % Comments to each level
   \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:

Final output

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.

1
  • Very good advice! Commented Jul 17, 2012 at 22:26
6

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}

output of code

1
  • 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
    Commented Jun 26, 2015 at 22:32
5

Here's a Forest solution.

\documentclass[tikz, border=5pt]{standalone}
\usepackage{forest}

\begin{document}
\begin{forest}
  for tree={
    circle,
    draw,
  },
  arrow just/.style={
    tikz+={
      \node [anchor=mid west] at (.mid -| e) {$\Rightarrow$ #1};
    },
  },
  colour me/.style={
    draw=#1,
    edge={draw=#1},
    text=#1,
  },
  trail/.style={
    colour me=#1,
    for ancestors={colour me=#1},
  },
  tikz+={\coordinate (e) at (current bounding box.east);}
  [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{forest}
\end{document}

Forest solution

3

Another solution to use the istgame package:

enter image description here

\documentclass{standalone}

\usepackage{amsmath}
\usepackage{istgame}

\begin{document}

\begin{istgame}
% tree
\setistOvalNodeStyle{6mm}
\xtdistance{15mm}{35mm}
\istrooto(0)[draw=red,red]{1}
  \istb[red]
  \istb
  \istb
  \endist
\xtdistance{15mm}{10mm}
\istrooto(1)(0-1)[draw=red,red]{3} 
  \istb[red]{}{4}[center,circle,draw,fill=white,red]
  \xtShowEndPoints[oval node]
  \istb{}{5}[center]
  \istb{}{5}[center]
  \endist
\istrooto(2)(0-2){3} 
  \istb{}{4}[center] 
  \istb{}{5}[center]
  \istb{}{5}[center]
  \endist
\istrooto(3)(0-3){3} 
  \istb{}{4}[center] 
  \istb{}{5}[center]
  \istb{}{5}[center]
  \endist
% level comments
\coordinate (z) at (3-3);
\coordinate (w) at ([xshift=1cm]z);
\node at (0-|w) [right] {$\Rightarrow$ 1st level arrow indicates here};
\node at (1-|w) [right] {$\Rightarrow$ 2nd level arrow indicates here};
\node at (z-|w) [right] {$\Rightarrow$ 3rd level arrow indicates here};
\end{istgame}

\end{document}

(ADDED)

Alternatively, you can replace the last part by the following codes (from the istgame version 2.0):

% level comments
\xtTimeLineH[draw=none](0){0}{5.5}{$\Rightarrow$ 1st level arrow indicates here}
\xtTimeLineH[draw=none](1){0}{5.5}{$\Rightarrow$ 2nd level arrow indicates here}
\xtTimeLineH[draw=none](3-3){0}{5.5}{$\Rightarrow$ 3rd level arrow indicates here}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .