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?

Lucas
  • 269

2 Answers2

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

  • Could we also do this with forest? (Curious mainly, as I have no need for this kind of tree.) – Alan Munn Apr 14 '20 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. –  Apr 14 '20 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 '20 at 21:43
  • @Vincent I only really knew this because I was playing with the mindmaps before. The structure here is like a mindmap. –  Apr 14 '20 at 21:54
  • @Schrödinger'scat thanks for the explanation. Is there any good text to learn tikz? – Lucas Apr 14 '20 at 22:51
  • 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. –  Apr 14 '20 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. –  Apr 15 '20 at 01:11
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}

Vincent
  • 20,157