5

I am drawing a recursion tree in latex using TikZ and my problem is some circles overlap and I can't seem to figure out why. Also, is there a way to put some text on the lines connecting parent nodes to their own children?

Here it is my code.

\documentclass[11pt,a4paper,oneside]{article}
\usepackage{fullpage}
\usepackage[italian]{babel}
\usepackage[utf8]{inputenc}
\usepackage{amsfonts}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{tikz}

\begin{document}
\begin{figure}[hb]
    \centering
    \begin{tikzpicture}[level/.style={sibling distance=30mm/#1}]
        \node[circle,draw](z){$n$}
            child{node [circle,draw] (a) {$\frac{n}{4}$}
                child{node [circle,draw] (d) {$\frac{n}{4^2}$}}
                child{node [circle,draw] (e) {$\frac{n}{4^2}$}}
                child{node [circle,draw] (f) {$\frac{n}{4^2}$}}
            }
            child{node [circle,draw] (b) {$\frac{n}{4}$}
                child{node [circle,draw] (g) {$\frac{n}{4^2}$}}
                child{node [circle,draw] (h) {$\frac{n}{4^2}$}}
                child{node [circle,draw] (k) {$\frac{n}{4^2}$}}
            }
            child{node [circle,draw] (c) {$\frac{n}{4}$}
                child{node [circle,draw] (l) {$\frac{n}{4^2}$}}
                child{node [circle,draw] (m) {$\frac{n}{4^2}$}}
                child{node [circle,draw] (n) {$\frac{n}{4^2}$}}
            };
        \path (a) -- (b) node [midway] {+};
        \path (b) -- (c) node [midway] {+};
        \path (d) -- (e) node [midway] {+};
        \path (e) -- (f) node [midway] {+};
        \path (f) -- (g) node [midway] {+};
        \path (g) -- (h) node [midway] {+};
        \path (h) -- (k) node [midway] {+};
        \path (k) -- (l) node [midway] {+};
        \path (l) -- (m) node [midway] {+};
        \path (m) -- (n) node [midway] {+};

    \end{tikzpicture}
\end{figure}
\end{document}
1
  • What text do you want to put on the edges? Is there a pattern to it?
    – cfr
    Oct 13 '16 at 2:06
6

You could also use forest and let it to compute minimum distances for you.

Note: I'm sure that, being a recursive diagram, following code could be simplified but I don't know how to do it. This is just an easy to understand solution.

\documentclass[11pt, a4paper,oneside]{article}
\usepackage{fullpage}
\usepackage[italian]{babel}
\usepackage[utf8]{inputenc}
\usepackage{amsfonts}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{forest}

\begin{document}
\begin{figure}[hb]
    \centering
    \begin{forest}
    [$n$, for tree={circle, draw}
        [$\frac{n}{4}$, name=a
            [$\frac{n}{4^2}$, name=d]
            [$\frac{n}{4^2}$, name=e]
            [$\frac{n}{4^2}$, name=f]]
        [$\frac{n}{4}$, name=b
            [$\frac{n}{4^2}$, name=g]
            [$\frac{n}{4^2}$, name=h]
            [$\frac{n}{4^2}$, name=i]]
        [$\frac{n}{4}$, name=c
            [$\frac{n}{4^2}$, name=j]
            [$\frac{n}{4^2}$, name=k]
            [$\frac{n}{4^2}$, name=l]]]
          \path (a) -- (b) node [midway] {+};
        \path (b) -- (c) node [midway] {+};
        \path (d) -- (e) node [midway] {+};
        \path (e) -- (f) node [midway] {+};
        \path (f) -- (g) node [midway] {+};
        \path (g) -- (h) node [midway] {+};
        \path (h) -- (i) node [midway] {+};
        \path (i) -- (j) node [midway] {+};
        \path (j) -- (k) node [midway] {+};
        \path (k) -- (l) node [midway] {+};
    \end{forest}
\end{figure}
\end{document}

enter image description here

Update: Following cfr advises, math content and s sep has been introduced.

\documentclass[11pt, a4paper,oneside]{article}
\usepackage{fullpage}
\usepackage[italian]{babel}
\usepackage[utf8]{inputenc}
\usepackage{amsfonts}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{forest}

\begin{document}
\begin{figure}[hb]
    \centering
    \begin{forest}
    [n, for tree={circle, draw, math content, s sep=1em}
        [\frac{n}{4}, name=a
            [\frac{n}{4^2}, name=d]
            [\frac{n}{4^2}, name=e]
            [\frac{n}{4^2}, name=f]]
        [\frac{n}{4}, name=b
            [\frac{n}{4^2}, name=g]
            [\frac{n}{4^2}, name=h]
            [\frac{n}{4^2}, name=i]]
        [\frac{n}{4}, name=c
            [\frac{n}{4^2}, name=j]
            [\frac{n}{4^2}, name=k]
            [\frac{n}{4^2}, name=l]]]
          \path (a) -- (b) node [midway] {+};
        \path (b) -- (c) node [midway] {+};
        \path (d) -- (e) node [midway] {+};
        \path (e) -- (f) node [midway] {+};
        \path (f) -- (g) node [midway] {+};
        \path (g) -- (h) node [midway] {+};
        \path (h) -- (i) node [midway] {+};
        \path (i) -- (j) node [midway] {+};
        \path (j) -- (k) node [midway] {+};
        \path (k) -- (l) node [midway] {+};
    \end{forest}
\end{figure}
\end{document}

enter image description here

2
  • You can use edge label to add labels to the edges with this method. (Trickier with mine.) I would increase the s sep a bit as the bottom nodes are a bit squeezed when the addition signs are added later. Also math content would let you omit the $ signs.
    – cfr
    Oct 13 '16 at 2:09
  • @cfr Thank you for the suggestions and your alternative answer.
    – Ignasi
    Oct 13 '16 at 6:41
3

For the overlapping nodes, the important observation is that sibling distance specifies the space between children of the same parent, not between all nodes on a given level. The relevant line in your example is

\begin{tikzpicture}[level/.style={sibling distance=30mm/#1}]

which specifies that siblings at level n (children of the same node) should be spaced out at distance 30/n mm from one another. So the nodes on level 1 (level 0 being the root) are 30mm apart. Meanwhile, a right child on level 2 is 15mm to the right of its parent, and a left child is 15mm to the left of its parent, which turns out to be the same place as the right child with of its parent's left sibling.

To fix this, you'll need to change that line. For example, if you expect to have a complete ternary tree with many layers and want the 3^n nodes on the nth layer to be evenly spaced (for all layers), you'd use

\begin{tikzpicture}[level/.style={sibling distance=120mm/3^#1}]

(here 120mm seems to do pretty well for the 3 layers you have, but you'd have to increase that scaling factor to avoid overlap in later layers). You can also set sibling distance explicitly for each layer:

\begin{tikzpicture}[level 1/.style={sibling distance=42mm}, level 2/.style={sibling distance=14mm}]

To add a label to an edge, append edge from parent node {Your Label} after the child node declaration, e.g.,

child{node [circle,draw] (a) {$\frac{n}{4}$} edge from parent node {Your Label}

You can style the edge label node just like any other node (e.g., use ...edge from parent node[left]... to place the label to the left of the edge midpoint).

3

Ignasi suggested that I might be able to 'improve' the Forest solution.

I have to say, that this code can scarcely be accused of being simpler. It is, however, more automated. Forest itself constructs all aspects of the tree given two pieces of information: the number of levels below the root and the number of branches from each non-terminal node.

It is also possible, though not required, to specify the factor used in the denominators. If this is not given, the number of branches plus 1 will be used.

By default, 2 levels and 3 branches are used, as in Ignasi's example.

To use the style, add rstyle to the tree's preamble.

  • rbranches=<integer> specifies the number of branches from each non-terminal node;
  • rlevels=<integer> specifies the number of levels below the root.

Should you need to override the factor used in the denominators, use

  • rdenom=<integer>.

Hence, we can draw 3 trees as follows.

First, we test the defaults to match Ignasi's example. I've added a little more spacing as I initially had no idea there were addition signs in the bottom level.

\begin{forest}
  rtree,
  []
\end{forest}

3x2

Now let's try a tree with the default number of branches but an additional level, but we'll make everything explicit here.

\begin{forest}
  rtree,
  rbranches'=3,
  rlevels'=3,
  []
\end{forest}

3x3

Finally, let's reduce the branching to 2 but increase the levels to 5.

\begin{forest}
  rtree,
  rbranches'=2,
  rlevels'=5,
  []
\end{forest}

2x5

Complete code:

% addaswyd o côd Ignasi: http://tex.stackexchange.com/a/333886/
\documentclass[border=10pt,tikz]{standalone}
\usepackage{forest}
\forestset{
  declare count register=rlevels,
  declare count register=rbranches,
  declare count register=rdenom,
  declare count register=rwait,
  rlevels'=2,
  rbranches'=3,
  rdenom'=0,
  rwait'=1,
  define long step={rup}{}{fake=root,first leaf,ancestors},
  rtree/.style={
    delay={
      repeat/.wrap pgfmath arg={
        {##1}{
          rwait'+=2,
          delay n/.wrap pgfmath arg={
            {########1}{
              where n children=0{
                repeat/.wrap pgfmath arg={
                  {################1}{
                    append={[]}
                  }
                }{rbranches},
              }{},
            }
          }{rwait},
        }
      }{rlevels},
    },
    before typesetting nodes={
      if={(rdenom)==0}{
        rdenom/.register=rbranches,
        rdenom'+=1,
      }{},
      for tree={
        circle,
        draw,
        math content,
        s sep+=5pt,
      },
      where level=0{
        content=n,
      }{
        if level=1{
          content=\frac{n}{\foresteregister{rdenom}},
        }{
          content/.wrap pgfmath arg={\frac{n}{\foresteregister{rdenom}^{##1}}}{level()},
        },
      },
    },
    before drawing tree={
      for rup={
        tempkeylista'=,
        for nodewalk/.wrap pgfmath arg={
          {fake=root,filter={descendants}{(level())==##1}}{tempkeylista/.option=name}
        }{level()},
        radd/.register=tempkeylista,
      },
    }
  },
  radd/.style={
    tikz+={
      \foreach \i [remember=\i, count=\k, remember=\i as \j] in {#1}
      \ifnum\k=1\relax\else\path  (\i) -- (\j) node [midway] {$+$}\fi;
    },
  },
}
\begin{document}
\begin{forest}
  rtree,
  []
\end{forest}
\begin{forest}
  rtree,
  rbranches'=3,
  rlevels'=3,
  []
\end{forest}
\begin{forest}
  rtree,
  rbranches'=2,
  rlevels'=5,
  []
\end{forest}
\end{document}

EDIT

This illustrates how to automatically add labels to the edges between parents and children based on a template filled in by Forest. For demonstration purposes, I've used the template

Step <level of recursion>: Branch <number of branch>

For most labels, the text is angled above the branch. If the number of branches is odd, the middle child's label is split over 2 lines and set horizontally, with a white fill behind to avoid the ugliness of the branch being drawn through it.

When labels are used, as in the default case, the tree is spaced out a bit to make room for them. This would need adjustment if the template differed markedly in size, of course.

Labels may be switched off using not rtree labels or switched on explicitly with rtree labels.

Using the extended style, the same code for the three trees as above produces automatically labelled versions.

first tree auto-labelled

second tree auto-labelled

third tree auto-labelled

% ateb: http://tex.stackexchange.com/a/333904/ addaswyd o côd Ignasi: http://tex.stackexchange.com/a/333886/
\documentclass[border=10pt,tikz]{standalone}
\usepackage{forest}
\forestset{
  declare count register=rlevels,
  declare count register=rbranches,
  declare count register=rdenom,
  declare count register=rwait,
  declare boolean register=rtree labels,
  rtree labels,
  rlevels'=2,
  rbranches'=3,
  rdenom'=0,
  rwait'=1,
  define long step={rup}{}{fake=root,first leaf,ancestors},
  rtree/.style={
    delay={
      repeat/.wrap pgfmath arg={
        {##1}{
          rwait'+=2,
          delay n/.wrap pgfmath arg={
            {########1}{
              where n children=0{
                repeat/.wrap pgfmath arg={
                  {################1}{
                    append={[, redge label/.wrap 2 pgfmath args={Step ################################################################1: Branch ################################################################2}{level()}{n()}]}
                  }
                }{rbranches},
              }{},
            }
          }{rwait},
        }
      }{rlevels},
    },
    before typesetting nodes={
      if={(rdenom)==0}{
        rdenom/.register=rbranches,
        rdenom'+=1,
      }{},
      for tree={
        circle,
        draw,
        math content,
        s sep+=5pt,
        if rtree labels={
          l sep+=15pt,
        }{},
      },
      where level=0{
        content=n,
      }{
        if level=1{
          content=\frac{n}{\foresteregister{rdenom}},
        }{
          content/.wrap pgfmath arg={\frac{n}{\foresteregister{rdenom}^{##1}}}{level()},
        },
      },
    },
    before packing={
      if rtree labels={
        where n children=0{
          !u.l sep+=30pt,
          !u.s sep+=20pt,
          if level=1{}{
            !uu.l sep+=20pt,
            if level=2{}{
              !uuu.l sep+=10pt,
            },
          },
        }{},
      }{},
    },
    before drawing tree={
      for rup={
        tempkeylista'=,
        for nodewalk/.wrap pgfmath arg={
          {fake=root,filter={descendants}{(level())==##1}}{tempkeylista/.option=name}
        }{level()},
        radd/.register=tempkeylista,
      },
    }
  },
  radd/.style={
    tikz+={
      \foreach \i [remember=\i, count=\k, remember=\i as \j] in {#1}
      \ifnum\k=1\relax\else\path  (\i) -- (\j) node [midway] {$+$}\fi;
    },
  },
  redge label/.style={
    if rtree labels={
      if={(n())<(((rbranches)+1)/2)}{
        edge label={node [midway, font=\scriptsize, above, sloped] {#1}},
      }{
        if={(n())>(((rbranches)+1)/2)}{
          edge label={node [midway, font=\scriptsize, above, sloped] {#1}},
        }{
          temptoksa={#1},
          split register={temptoksa}{:}{temptoksb,temptoksc},
          edge label/.wrap 2 pgfmath args={node [midway, font=\scriptsize, align=center, fill=white] {##1:\\##2}}{temptoksb}{temptoksc},
        },
      },
    }{},
  },
}
\begin{document}
\begin{forest}
  rtree,
  []
\end{forest}
\begin{forest}
  rtree,
  rbranches'=3,
  rlevels'=3,
  []
\end{forest}
\begin{forest}
  rtree,
  rbranches'=2,
  rlevels'=5,
  []
\end{forest}
\end{document}
1
  • Step ################################################################1: Branch ################################################################2 seems ridiculous. Isn't there another way?!!
    – cfr
    Oct 13 '16 at 22:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.