5

How can I achieve the drawing of a depth-first traversal of a binary tree like in this picture ?

Alan Munn
  • 218,180
projetmbc
  • 13,315

2 Answers2

11

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc, arrows}
\begin{document}
\begin{tikzpicture}[->,>=stealth',every node/.style={circle,draw},level 1/.style={sibling distance=50mm},level 2/.style={sibling distance=20mm},level 3/.style={sibling distance=12mm},
%scale=0.7, transform shape
]
\node (nA){A}
   child { node (nB) {B}
              child { node (nD) {D}
                         child { node (nH) {H} }
                       }
              child {  node (nE) {E}
                         child { node (nI) {I} }
                         child { node (nJ) {J} }
                       }
            }
   child { node (nC) {C}
              child { node (nF) {F}
                         child { node (nK) {K}  }
                         child { node (nL) {L} }
                         child { node (nM) {M} }
                       }
              child {  node (nG) {G} }
             };

  \draw[->,blue,rounded corners,dashed,line width=0.7pt]
    ($(nA) + (-0.4,0.2)$) --
    ($(nB) +(-0.3,0.4)$) --
    ($(nB) +(-0.6,0.0)$) --
    ($(nD)  +(-0.4,0.3)$) --
    ($(nD)  +(-0.5,0.0)$) --
    ($(nH)  +(-0.5,0.0)$) --
    ($(nH)  +(-0.4,-0.35)$) --
    ($(nH)  +(0.0,-0.5)$) --
    ($(nH)  +(0.4,-0.35)$) --
    ($(nH)  +(0.5,0.0)$) --
%    ($(nD)  +(0.45,-0.2)$) --
    ($(nD)  +(0.45,0.0)$) --
    ($(nB)  +(0.0,-0.4)$) --
    ($(nE)  +(-0.45,0.0)$) --
    ($(nI)  +(-0.45,0.0)$) --
    ($(nI)  +(-0.35,-0.35)$) --
    ($(nI)  +(0.0,-0.45)$) --
    ($(nI)  +(0.35,-0.35)$) --
    ($(nI)  +(0.4,0.0)$) --
    ($(nE)  +(0.0,-0.4)$) --
    ($(nJ)  +(-0.45,0.0)$) --
    ($(nJ)  +(-0.35,-0.35)$) --
    ($(nJ)  +(0.0,-0.45)$) --
    ($(nJ)  +(0.35,-0.35)$) --
    ($(nJ)  +(0.45,0.0)$) --
    ($(nE)  +(0.4,0.2)$) --
    ($(nB)  +(0.4,0.0)$) --
    ($(nA)  +(0.0,-0.4)$) --
    ($(nC)  +(-0.4,0.0)$) --
%    ($(nF)  +(-0.6,0.0)$) --
    ($(nK)  +(-0.5,0.1)$) --
    ($(nK)  +(-0.4,-0.35)$) --
    ($(nK)  +(0.0,-0.5)$) --
    ($(nK)  +(0.4,-0.3)$) --
    ($(nF)  +(-0.15,-0.4)$) --
    ($(nL)  +(-0.5,0.0)$) --
    ($(nL)  +(-0.4,-0.35)$) --
    ($(nL)  +(0.0,-0.5)$) --
    ($(nL)  +(0.4,-0.35)$) --
    ($(nL)  +(0.5,0.0)$) --
    ($(nF)  +(0.15,-0.4)$) --
    ($(nM)  +(-0.5,0.0)$) --
    ($(nM)  +(-0.4,-0.35)$) --
    ($(nM)  +(0.0,-0.5)$) --
    ($(nM)  +(0.4,-0.35)$) --
    ($(nM)  +(0.5,0.2)$) --
    ($(nF)  +(0.4,0.0)$) --
    ($(nC)  +(0.0,-0.4)$) --
    ($(nG)  +(-0.5,0.0)$) --
    ($(nG)  +(-0.4,-0.35)$) --
    ($(nG)  +(0.0,-0.5)$) --
    ($(nG)  +(0.4,-0.35)$) --
    ($(nG)  +(0.5,0.1)$) --
    ($(nC) +(0.6,0.0)$) --
    ($(nC) +(0.3,0.4)$) --
    ($(nA) + (0.4,0.2)$);
\end{tikzpicture}
\end{document}
Jake
  • 232,450
Humberto Longo
  • 134
  • 1
  • 2
3

This solution is not as pretty as the hand-drawn version. However, it is somewhat automatic. That said, it will certainly produce unwanted results if a tree differs too significantly from the one I tested it on.

The solution uses forest (of course). I wanted to get intersections using the intersections library in order to draw neater paths when the number of children is 2 or more. However, I can't make this work properly as I can't get things to expand in the right places at the right times. So this is cruder and more fragile. (That is, it is uglier and will even more likely break.)

Caveat emptor...

auto-enclosure

\documentclass[tikz, border=5pt]{standalone}
\usepackage{forest}
\usetikzlibrary{arrows.meta}
\begin{document}
\tikzset{
  enclosure/.style={
    draw=blue,
  }
}
\begin{forest}
  for tree={
    circle,
    draw,
    outer sep=2pt,
    s sep+=2.5pt,
    edge={shorten <=-2pt, shorten >=-2pt},
    if level=0{
      for children={
        if n=1{
          tikz={
            \draw [enclosure] (.west) [out=90, in=-135] to (.north west) -- (!u.north west);
            \draw [enclosure] (.east) -- (!n.north west |- !u.south) -- (!n.north west) [out=-135, in=90] to (!n.west);
          },
        }{
          if n'=1{
            tikz={
              \draw [enclosure, -{Stealth[]}] (.east) [out=90, in=-45] to (.north east) -- (!u.north east) ;
              \draw [enclosure] (.west) -- (!p.north east |- !u.south) -- (!p.north east) [out=-45, in=90] to (!p.east);
            },
          }{}
        }
      },
    }{
      if n children=1{
        for children={
          tikz={
            \draw [enclosure] (.west) -- (!u.west) [out=90, in=-135] to (!u.north west)  (.east) -- (!u.east) [out=90, in=-45] to (!u.north east) ;
          },
        }
      }{
        if n children=2{
          for children={
            if n=1{
              tikz={
                \draw [enclosure] (.west) [out=90, in=-135] to (.north west) -- (!u.west) (.east) [out=90, in=-45] to (.north east) -- (!u.south);
              },
            }{
              if n'=1{
                tikz={
                  \draw [enclosure] (.east) [out=90, in=-45] to (.north east) -- (!u.east) (.west) [out=90, in=-135] to (.north west) -- (!u.south);
                },
              }{}
            }
          },
        }{
          for children={
            if n=1{
              tikz={
                \draw [enclosure] (.west) [out=90, in=-135] to (.north west) -- (!u.west);
                \draw [enclosure] (.east) -- (!n.north west |- !u.south) -- (!n.north west) [out=-135, in=90] to (!n.west);
              },
            }{
              if n'=1{
                tikz={
                  \draw [enclosure] (.east) [out=90, in=-45] to (.north east) -- (!u.east);
                  \draw [enclosure] (.west) -- (!p.north east |- !u.south) -- (!p.north east) [out=-45, in=90] to (!p.east);
                },
              }{}
            }
          },
        }
      },
      if n children=0{
        afterthought={
          \draw [enclosure] (.west) [out=-90, in=-180] to (.south) [out=0, in=-90] to (.east);
        }
      }{}
    },
    if={isodd(n_children)}{
      for children={
        if={equal(n,int((n_children("!u")+1)/2))}{
          calign with current
        }{}
      }
    }{},
  }
  [A
    [B
      [E]
      [F
        [K]
        [L]
        [M]
      ]
      [G]
    ]
    [C
      [H]
    ]
    [D
      [I]
      [J
        [N]
        [O]
      ]
    ]
  ]
\end{forest}

\end{document}
cfr
  • 198,882