9

I would like to know how to write the following graph in LaTeX:

Enter image description here

I'm just a beginner in LaTeX, so I tried to follow this example, but I could not make it work. Using

\begin{document}

\begin{tikzpicture}[>=stealth',shorten >=1pt,node distance=2cm,on grid,initial/.style={}]
\node[state] (T0) {$0$};
\node[state] (T1) [above =of T0] {$1$};
\node[state] (T2) [right =of T1] {$2$};
\node[state] (T3) [below =of T0] {$4$};
\node[state] (T4) [left =of T3] {$5$};
\node[state] (T5) [right =of T3] {$3$};

\tikzset{every node/.style={fill=white}}
\path (T0) edge (T1);
\path (T0) edge (T2);
\path (T0) edge (T3);
\path (T0) edge (T4);
\path (T0) edge (T5);
\end{tikzpicture}

\end{document}

I get

Enter image description here

I did not finish because it was not good. How can I fix it?

2 Answers 2

8

Here's a way to do it.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows, positioning}

\begin{document}

\begin{tikzpicture}[every node/.style={shape=circle,fill=black,circle,inner sep=1pt}]
    \node[label=above:{$0$}] (T0) {}
        child [grow=126] {node[label=above right:{$1$}] (T1) {}
            child {node[label=above:{$b_1$}] (Tb1) {}}
            child {node[label=left:{$a_1$}] (Ta1) {}} }
        child [grow= 54] {node[label=above left:{$2$}] (T2) {}
            child {node[label=right:{$b_2$}] (Tb2) {}}
            child {node[label=above:{$a_2$}] (Ta2) {}} }
        child [grow=344] {node[label=above:{$3$}] (T3) {}
            child {node[label=right:{$a_3$}] (Ta3) {}}
            child {node[label=right:{$b_3$}] (Tb3) {}} }
        child [grow=270] {node[label=right:{$4$}] (T4) {}
            child {node[label=left:{$a_4$}] (Ta4) {}}
            child {node[label=right:{$b_4$}] (Tb4) {}} }
        child [grow=198] {node[label=above:{$5$}] (T5) {}
            child {node[label=left:{$a_5$}] (Ta5) {}}
            child {node[label=left:{$b_5$}] (Tb5) {}} };
\end{tikzpicture}

\end{document}

1
  • Nice! I think I get the structure. Thanks!
    – Lucas
    Apr 14, 2020 at 18:19
13

Such trees can conveniently be drawn with the grow cyclic option. This example is very much like the one of the pgf manual v3.1.5 on p. 845

enter image description here

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{trees}
\begin{document}
\begin{tikzpicture}[grow cyclic,nodes={circle,fill,inner sep=1.5pt},
level 1/.style={level distance=2.5cm,sibling angle=-360/5},
level 2/.style={font=\footnotesize, level distance=2cm,sibling angle=40},
rotate=-360/20,semithick]

\node {} % root
child foreach \X in {1,...,5}
{node[label=540/5-\X*360/5:\X]{} 
      child { node[label=180+360/20-\X*360/5-20:$b_\X$] {} }
      child { node[label=180+360/20-\X*360/5+20:$a_\X$] {} }
  };
\end{tikzpicture}
\end{document}

enter image description here

One can make it somewhat more versatile by using the actual sibling angles in the label anchor computation. It is stored in \pgfkeysvalueof{/tikz/sibling angle} and differs from level to level. (No, I am not proud of the \xdef but that way the user has only to adjust the angle once.)

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{trees}
\begin{document}
\begin{tikzpicture}[grow cyclic,nodes={circle,fill,inner sep=1.5pt},
level 1/.style={level distance=2.5cm,sibling angle=-360/5},
level 2/.style={font=\footnotesize, level distance=2cm,sibling angle=60},
rotate=-360/20,semithick]

\node[label=above:$0$] {} % root
child foreach \X in {1,...,5}
{node[label={-1.5*\pgfkeysvalueof{/tikz/sibling angle}+\pgfkeysvalueof{/tikz/sibling angle}*\X}:\X]{\xdef\LevelOneSiblingAngle{\pgfkeysvalueof{/tikz/sibling angle}}} 
      child { node[label=180-\LevelOneSiblingAngle/5+\X*\LevelOneSiblingAngle-\pgfkeysvalueof{/tikz/sibling angle}/2:$b_\X$] {} }
      child { node[label=180-\LevelOneSiblingAngle/5+\X*\LevelOneSiblingAngle+\pgfkeysvalueof{/tikz/sibling angle}/2:$a_\X$] {} }
  };
\end{tikzpicture}
\end{document}

enter image description here

One can also hack the growth function to record the current rotation angle to make the placement of the angles more convenient. The idea of hacking the growth function is not at all new, one can see very nice examples e.g. here but perhaps this hack is. The slope of the current edge is now available in a function currangle. I decided not to include the overall rotation, which is set by rotate, because I think it is cleaner this way. It is conceivable that this hack is also useful for mindmaps.

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{trees}
\makeatletter
\def\tikz@grow@circle@record{%
  \pgfmathsetmacro{\currentrotation}{(\pgfkeysvalueof{/tikz/sibling angle})*(-.5-.5*\tikznumberofchildren+\tikznumberofcurrentchild)}%
  \pgftransformrotate{\currentrotation}%
  \expandafter\xdef\csname tikz@grow@circle@rot@\romannumeral\tikztreelevel\endcsname{\currentrotation}%
  \pgftransformxshift{\the\tikzleveldistance}%
}%
\pgfmathdeclarefunction{currangle}{0}{\begingroup
\pgfmathparse{(\pgfkeysvalueof{/tikz/sibling angle})*(-.5-.5*\tikznumberofchildren+\tikznumberofcurrentchild)}%
\ifcase\tikztreelevel
\or
\or
\pgfmathparse{\pgfmathresult+\tikz@grow@circle@rot@i}%
\or
\pgfmathparse{\pgfmathresult+\tikz@grow@circle@rot@i+\tikz@grow@circle@rot@ii}%
\fi
\typeout{\the\tikznumberofcurrentchild:\pgfmathresult}%
\pgfmathsmuggle\pgfmathresult
\endgroup}
\tikzset{
  recorded grow cyclic/.style={
    edge from parent/.append style={reset cm},
    growth function=\tikz@grow@circle@record,
  }
}%
\tikzoption{recorded clockwise from}{\let\tikz@grow=\tikz@grow@circle@cw@from@record\def\tikz@grow@circle@from@start{#1}}%
\makeatother
\begin{document}
\begin{tikzpicture}[recorded grow cyclic,nodes={circle,fill,inner sep=1.5pt},
level 1/.style={level distance=2.5cm,sibling angle=-360/5},
level 2/.style={font=\footnotesize, level distance=2cm,sibling angle=60},
semithick,rotate=-360/20]

\node[label=above:$0$] {} % root
child foreach \X in {1,...,5}
{node[label={currangle-90-360/20}:\X]{} 
      child { node[label={currangle-360/20}:$b_\X$] {} }
      child { node[label={currangle-360/20}:$a_\X$] {} }
  };
\end{tikzpicture}
\end{document}

enter image description here

7
  • Could we also do this with forest? (Curious mainly, as I have no need for this kind of tree.)
    – Alan Munn
    Apr 14, 2020 at 21:33
  • @AlanMunn I think it is not built in but presumably the answer is yes because you can force forest to use certain coordinates for the nodes. However, once you do that you lose all the automatic layout machinery which makes forest so powerful.
    – user194703
    Apr 14, 2020 at 21:36
  • @Schrödinger'scat This is great, thanks! When I wrote my answer I felt there was a more efficient way to do it (I'm still a beginner in tikz). I tried foreach loops, but I wasn't sure how to place the labels properly.
    – Vincent
    Apr 14, 2020 at 21:43
  • 2
    @Corrêa I think the pgfmanual is decent. Let me also advertise this trick: perform a Google picture search (or plain Google search) for site:tex.stackexchange.com <search term(s)> and look at the posts whose results come close to what you want. This can help you to see what others did and you can learn from that.
    – user194703
    Apr 14, 2020 at 22:58
  • 1
    @AlanMunn While I was not able to get any close-to-reasonable output in forest I added an example of hacking the growth function. While the usage is far less convenient than forest, it in principle allows one to also draw the trees more programmatically. Of course, hacking the growth is not precisely a new technique.
    – user194703
    Apr 15, 2020 at 1:11

You must log in to answer this question.

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