21

Is there some way to draw a B+ tree in latex? It would look something like the picture below (ignoring the animations)

Animation linked here: https://i.stack.imgur.com/JRcmY.gif

Screenshot of the start of the animation:

Screenshot of a B+ tree

Jake
  • 232,450
  • As you'll soon see in the answers below - the package tikz is great resource for drawing graphs when you know the absolute positions of the nodes. – Hooked May 04 '11 at 04:22
  • Welcome to TeX.sx, DamonKashu! I've added a screenshot of the animation you linked to. I hope this image captures what you are trying to achieve. – Jake May 04 '11 at 04:24

3 Answers3

22

I would do this in TikZ. Section 18.1 of the version 2.10 manual shows how to make trees. The nodes on the trees are a little nonstandard, but perhaps section 16.3 on multi-part nodes would be helpful.

Here's a quick mockup:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes}
\begin{document}
\begin{center}
\begin{tikzpicture}
\tikzstyle{bplus}=[rectangle split, rectangle split horizontal,rectangle split ignore empty parts,draw]
\tikzstyle{every node}=[bplus]
\tikzstyle{level 1}=[sibling distance=60mm]
\tikzstyle{level 2}=[sibling distance=15mm]
\node {15} [->]
  child {node {3 \nodepart{two} 7}
    child {node {1 \nodepart{two} 2}}
    child {node {4 \nodepart{two} 6}}
    child {node {8 \nodepart{two} 9}}    
  } 
  child {node {21 \nodepart{two} 28 \nodepart{three} 32 \nodepart{four} 50}
    child {node {17 \nodepart{two} 20}}
    child {node {22 \nodepart{two} 25}}
    child {node {28 \nodepart{two} 30}}    
    child[sibling distance=25mm] {node {34 \nodepart{two} 38 \nodepart{three} 44 \nodepart{four} 47}}    
    child[sibling distance=25mm] {node {53 \nodepart{two} 54 \nodepart{three} 60 \nodepart{four} 88}}    
  }
;\end{tikzpicture}
\end{center}

\end{document}

sample code output

It's going to be more work to get the vertical lines doubled like in your example. The code for the rectangle split shape may need to be altered.

Matthew Leingang
  • 44,937
  • 14
  • 131
  • 195
  • 2
    In the US B+ is a grade students might receive if they do "good" work in a course. So "B+ tree" sounds to me a little strange. Couldn't I have an "A- tree" instead? :-) – Matthew Leingang May 04 '11 at 16:47
  • This is the most comprehensive result when searching for "draw b+ tree in latex" so I figured I'd add a tip for styling each node to look more like a B+ tree.

    Suppose your B+ tree has 2 keys per node. To create the little empty rectangles surrounding each node, you can add the options rectangle split parts = 5, rectangle split empty part width=0.01mm, rectangle split every empty part={} to tikzstyle. Then you can create a function \newcommand \bpformat [2] {node{ \nodepart{two} #1 \nodepart{four} #2 }} & fill nodes with \child {\bpformat{3}{7}} and so on. ex: i.imgur.com/noeD0.png

    – maksim May 10 '12 at 01:50
  • @maksim: Thanks for the contribution. I feel like the "TikZ way" would be to create a new node shape like rectangle that drew the extra vertical lines. – Matthew Leingang May 10 '12 at 13:08
  • I see what you're saying. If we made a new shape, how could we control the way individual cells overlapped, so that the extra vertical lines would be in the correct spots? – maksim May 13 '12 at 23:23
  • The trouble is that even rectangle shapes are very complicated to define. The rectangle split shape is in pgflibraryshapes.multipart.code.tex. Perhaps a decoration can be applied to the background path to double vertical segments but not horizontal? – Matthew Leingang May 08 '13 at 16:29
11

I found an .sty file by Prof. Wei Wang from University of New South Wales which seems pretty nice:

http://www.cse.unsw.edu.au/~weiw/tools.html

Example

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{weiwBTree}
\typeout{Document Style `weiw_BTree - Support drawing B+-Tree (ver 0.999)}

\RequirePackage{tikz}
\RequirePackage{ifthen}

% use libraries
\usetikzlibrary{arrows,shapes,snakes,matrix}


%% global declaration
\tikzstyle{btreeptr} = [draw, semithick, fill=blue!50, minimum height=2em]
\tikzstyle{btreeval} = [draw, semithick, fill=yellow!30, minimum size=2em]
\tikzstyle{btreevale} = [draw,semithick, fill=green!30, minimum size=2em]
\tikzstyle{btlink} = [draw, semithick, ->, >=triangle 45]

%% macro
%% helper macros
\newcommand{\suppressemptystr}[1]{% leave blank for entries in leaf nodes
  \ifthenelse{\equal{#1}{}}%
  {%
    \relax%
  }%
  % Else
  {%
    #1\textsuperscript{*}%
  }%
}%

\newcommand{\xyshift}[3]{% help to place the nodes
  \begin{scope}[xshift=#1, yshift=#2]
    #3
  \end{scope}%
}

%% Common btree macros
\newcommand{\btreelink}[2]{% #1: src node; #2: dest node; 
  \draw[btlink] ([yshift=3pt] #1.south) -- (#2-b.north);
}

\newcommand{\btreelinknorth}[2]{% #1: src node; #2: dest node; 
  \draw[btlink] ([yshift=3pt] #1.south) -- (#2.north);
}

\newcommand{\btreetriangle}[2]{% #1: node name; #2 text inside
  \node[anchor=north, regular polygon, regular polygon sides=3, draw] (#1) {#2};
}

%%======================================================================
%% btree with capacity = 4
\newcommand{\btreeinodefour}[5]{%
  \matrix [ampersand replacement=\&] (#1)
  {
    \node[btreeptr] (#1-1) {\vphantom{1}}; \& \node[btreeval] (#1-a) {#2}; \&
    \node[btreeptr] (#1-2) {\vphantom{1}}; \& \node[btreeval] (#1-b) {#3}; \&
    \node[btreeptr] (#1-3) {\vphantom{1}}; \& \node[btreeval] (#1-c) {#4}; \&
    \node[btreeptr] (#1-4) {\vphantom{1}}; \& \node[btreeval] (#1-d) {#5}; \&
    \node[btreeptr] (#1-5) {\vphantom{1}}; \\
  };
}
\newcommand{\btreelnodefour}[5]{%
  \matrix [ampersand replacement=\&, outer sep=0pt, matrix anchor=north] (#1)
  {
    \node[btreevale] (#1-a) {\suppressemptystr{#2}}; \&
    \node[btreevale] (#1-b) {\suppressemptystr{#3}}; \&
    \node[btreevale] (#1-c) {\suppressemptystr{#4}}; \&
    \node[btreevale] (#1-d) {\suppressemptystr{#5}}; \\
  };
}

%%======================================================================
%% btree with capacity = 3
\newcommand{\btreeinodethree}[4]{%
  \matrix [ampersand replacement=\&] (#1)
  {
    \node[btreeptr] (#1-1) {\vphantom{1}}; \& \node[btreeval] (#1-a) {#2}; \&
    \node[btreeptr] (#1-2) {\vphantom{1}}; \& \node[btreeval] (#1-b) {#3}; \&
    \node[btreeptr] (#1-3) {\vphantom{1}}; \& \node[btreeval] (#1-c) {#4}; \&
    \node[btreeptr] (#1-4) {\vphantom{1}}; \\
  };
}
\newcommand{\btreelnodethree}[4]{%
  \matrix [ampersand replacement=\&, outer sep=0pt, matrix anchor=north] (#1)
  {
    \node[btreevale] (#1-a) {\suppressemptystr{#2}}; \&
    \node[btreevale] (#1-b) {\suppressemptystr{#3}}; \&
    \node[btreevale] (#1-c) {\suppressemptystr{#4}}; \\
  };
}
%%======================================================================






%% simple example
%  \begin{center}
%    \scalebox{0.7}{
%      \begin{tikzpicture}
%        % 
%        \btreeinodefour{root}{13}{17}{24}{30};
%        \xyshift{-40mm}{-20mm}{\btreelnodefour{n1}{2}{3}{5}{7}}
%        \xyshift{-0mm}{-20mm}{\btreelnodefour{n2}{14}{16}{}{}}
%        \xyshift{40mm}{-20mm}{\btreelnodefour{n3}{19}{20}{22}{}}
%        \xyshift{80mm}{-20mm}{\btreelnodefour{n4}{24}{27}{29}{}}
%        \xyshift{120mm}{-20mm}{\btreelnodefour{n5}{33}{34}{38}{39}}
%        %
%        \foreach \x in {1,2,...,5} { \btreelink{root-\x}{n\x} }
%      \end{tikzpicture}
%    }
%  \end{center}
xji
  • 1,275
  • This should be the top answer. This package is very neat. (+1) – Columbo Feb 22 '16 at 17:06
  • Does anyone know how to add the arrows between neighbours? – Parth Oct 08 '16 at 20:57
  • The link here is broken and I can't find a current webpage for Dr. Wei Wang. Does anyone know where one can find this now? – Kyle Apr 16 '23 at 15:09
  • As my student pointed out, use the Wayback Machine: https://web.archive.org/web/20120430233547/http://www.cse.unsw.edu.au/~weiw/tools.html – Kyle Apr 18 '23 at 01:08
2

http://tug.org/PSTricks/main.cgi?file=pst-tree/pst-tree#binary can be modified to your needs