2

I'm trying to draw a binary tree using tikz. I use shift option to define the relative position of child nodes. But as the tree grows, the nodes start to overlap if I use a fixed shift. I'm able to get around this by manually specifying the location of children nodes. But is there a better way to do it?

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,arrows,fit,matrix,positioning}
\tikzset
{
        treenode/.style = {circle, draw=black, align=center, minimum size=1cm},
        subtree/.style  = {isosceles triangle, draw=black, align=center, minimum height=0.5cm, minimum width=0.5cm, shape border rotate=90, anchor=north},
        process/.style={rectangle, minimum width=2cm, minimum height=1cm, align=center, text width=2cm, draw},
        connector/.style={circle, minimum size=1cm, align=center, text width=0.5cm, draw},
        arrow/.style={thick, ->, >=stealth}
}
\usepackage{circuitikz}
\begin{document}
\begin{tikzpicture}
\newcommand\xShift{1.5}
\newcommand\yShift{1}
\node(x) [treenode] at (0, 0) {100};
\node(xl) [treenode] at ([shift=({-\xShift,-\yShift})]x) {50};
\node(xr) [treenode] at ([shift=({\xShift,-\yShift})]x) {200};
\node(xll) [treenode] at ([shift=({-\xShift,-\yShift})]xl) {25};
\node(xlr) [treenode] at ([shift=({\xShift,-\yShift})]xl) {70};
\node(xlll) [ground] at ([shift=({-\xShift,-\yShift})]xll) {};
\node(xllr) [subtree] at ([shift=({\xShift,-\yShift})]xll) {};
\node(xlrl) [treenode] at ([shift=({-\xShift,-\yShift})]xlr) {60};
\node(xlrr) [subtree] at ([shift=({\xShift,-\yShift})]xlr) {};
\draw[->] (x) -- (xl);
\draw[->] (x) -- (xr);
\draw[->] (xl) -- (xll);
\draw[->] (xl) -- (xlr);
\draw[->] (xll) -- (xlll);
\draw[->] (xll) -- (xllr.north);
\draw[->] (xlr) -- (xlrl);
\draw[->] (xlr) -- (xlrr.north);
\end{tikzpicture}
\end{document}

enter image description here

Related question Draw a binary tree using tikz

2
  • Use graphdrawing library and run with lualatex
    – skpblack
    Nov 3 '14 at 21:36
  • thank you. I tried using it. But since I have three different shapes, it doesn't come out clean. For example, to connect 25 and its right subtree which is a triangle, I'm not able to specify that the arrow should be on the north of the triangle.
    – arunmoezhi
    Nov 3 '14 at 22:08
2

You might try using a matrix of nodes:

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{shapes.geometric,matrix}
\tikzset
{
  treenode/.style = {circle, draw=black, align=center, text centered, minimum size=1cm},
  subtree/.style  = {isosceles triangle, draw=black, align=center, minimum height=0.5cm, minimum width=0.5cm, shape border rotate=90},
  phantom/.style = {draw=none, minimum size=0pt, inner sep=0pt, outer sep=0pt},
}
\usepackage{circuitikz}
\begin{document}
  \begin{tikzpicture}
    \matrix (mat) [matrix of nodes, nodes={treenode}]
      {
        &[5mm] &[5mm] &[5mm] 100 &[5mm] \\[5mm]
        & & 50 & & 200 \\[5mm]
        & 25 & & 70 & \\[5mm]
        |[phantom]| {} & & 60 & &  |[subtree]| {} \\
        & & |[subtree]| {} & &\\
      };
    \node [ground] at (mat-4-1) {};
    \begin{scope}[draw, ->]
      \draw (mat-1-4) -- (mat-2-3);
      \draw (mat-1-4) -- (mat-2-5);
      \draw (mat-2-3) -- (mat-3-2);
      \draw (mat-3-2) -- (mat-4-3);
      \draw (mat-2-3) -- (mat-3-4);
      \draw (mat-3-4) -- (mat-4-3);
      \draw (mat-3-4) -- (mat-4-5.north);
      \draw (mat-3-2) -- (mat-4-1.north);
    \end{scope}
  \end{tikzpicture}
\end{document}

nodes

EDIT

In response to the correction in the comment: in this case you could just adjust the matrix accordingly. However, I would probably draw a tree in this case instead. For example:

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{shapes.geometric}
\usepackage{forest}
\usepackage{circuitikz}
\begin{document}
  \tikzset{/forest,
    subtree/.style={isosceles triangle, draw=black, align=center, minimum height=0.5cm, minimum width=0.5cm, shape border rotate=90, child anchor=north, anchor=north, tier=terminus},
    terminus/.style={draw=none, inner sep=0pt, outer sep=0pt, minimum height=0pt, minimum width=0pt, tier=terminus},
  }
  \begin{forest}
    for tree={
      edge path={
        \noexpand\path [->, \forestoption{edge}] (!u.parent anchor) -- (.child anchor) \forestoption{edge label};
      },
      calign=fixed edge angles,
      calign angle=45,
      circle,
      draw=black,
      align=center,
      text centered,
      minimum size=10mm,
    }
    [100
      [50
        [25
          [, terminus, name=ground here]
          [, subtree]
        ]
        [70
          [60]
          [, subtree]
        ]
      ]
      [200
      ]
    ]
    \node [ground] at (ground here) {};
  \end{forest}
\end{document}

tree

2
  • I apologize for being not clear. The right child of 25 is a subtree and the left child of 70 is a node with value 60. I do not want them to overlap.
    – arunmoezhi
    Nov 3 '14 at 23:11
  • 1
    @arunmoezhi Hmm... yes, that would have been easier. See my update. The revised question is more straightforward: I'd assumed that the problem was needing nodes with multiple parents. If you don't need that, a tree is the simplest solution, I think.
    – cfr
    Nov 3 '14 at 23:57

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.