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, 2014 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, 2014 at 22:08

1 Answer 1

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, 2014 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, 2014 at 23:57

You must log in to answer this question.

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