- You can use
{}
instead of \mbox{}
to save yourself some typing when creating empty nodes. As ipavlic points out in his comment, you can also use the nodes in empty cells
key. This means that you can't specify all the extra gaps between the columns in the first row, because that would create a lot of incorrect empty nodes. Rather, you have to specify the extra gaps in the row where they are first used.
- You need to use
column 1/.style={nodes={minimum height=0.8cm}}
to change the node behaviour. If you don't use nodes=...
, you are basically changing the options that apply to the matrix as a whole, not the nodes (see Matrix of nodes column style inconsistency for more on that).
- It doesn't change the center, but rather the label is assigned the node name (
M-1-1
). You can prevent this by adding the option every label/.append style={name={}}
to the matrix. (see example at the end of the answer for a demonstration)
That's the normal behaviour of specifying a node name without an anchor. Quote from the pgfmanual, section 16.11: "When you say (x)--(1,1)
, the --
path operation will not draw a line from the center of x
, but from the border of x
in the direction going towards (1,1)
"
In order to make the lines overlap, the distance between the columns has to be -\pgflinewidth
. See TikZ matrix as a replacement for tabular.
In How should I draw a singly/double linked list?, the *-
line starts at the horizontal position of <node>.two
of the multipart node, which is not the center of the second node part, but actually shifted slightly to the left (replace *->
with --
to see where the line actually starts). In the case of the *-
arrow style, that's a convenient thing. Since you don't use multipart nodes, but one node for each rectangle, you don't have that anchor, and will have to resort to using shorten < = -2pt
.
Here's your code with the suggested changes:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows,fit}
\tikzset{circarrow/.style={
*->,
shorten <=-2pt
}
}
\begin{document}
\begin{tikzpicture}[>=stealth]
\matrix (M) [matrix of nodes,%
column sep=-\pgflinewidth,%
row sep=1mm,%
nodes in empty cells,
nodes={draw, fill=gray!20,%
minimum width=.5cm, outer sep=0pt,%
minimum height=.7cm, anchor=center},
column 1/.style={nodes={minimum height=.8cm}}]%
{
&[2mm] 2 & &[2mm] 5 & / \\
& 1 & & 5 & &[2mm] 3 & &[2mm] 4 & / \\
& 2 & & 5 & & 3 & /\\
};
\foreach \i in {1,2,3}{
\path (M-\i-1) [late options={label=left:\i}];
\draw[->] (M-\i-1)--(M-\i-2.west);
\draw[->] (M-\i-3.center)--(M-\i-4.west);
}
\draw[->] (M-2-5.center)--(M-2-6.west);
\draw[->] (M-2-7.center)--(M-2-8.west);
\draw[->] (M-3-5.center)--(M-3-6.west);
\begin{scope}[yshift=-3cm]
\matrix (M) [matrix of nodes,%
column sep=-\pgflinewidth,%
row sep=1mm,%
nodes in empty cells,
nodes={draw, fill=gray!20,%
minimum width=.5cm, outer sep=0pt,%
minimum height=.7cm, anchor=center},
column 1/.style={nodes={minimum height=.8cm}},
every label/.append style={name={}}]%
{
|[label=left:1]| &[2mm] 2 & &[2mm] 5 & / \\
|[label=left:2]|& 1 & & 5 & &[2mm] 3 & &[2mm] 4 & / \\
|[label=left:3]| & 2 & & 5 & & 3 & / & & \\
};
\foreach \i in {1,2,3}{
%\path (M-\i-1) [late options={label=left:\i}];
\draw[->] (M-\i-1)--(M-\i-2.west);
\draw[->] (M-\i-3.center)--(M-\i-4.west);
}
\draw[circarrow] (M-2-5.center)--(M-2-6.west);
\draw[circarrow] (M-2-7.center)--(M-2-8.west);
\draw[circarrow] (M-3-5.center)--(M-3-6.west);
\end{scope}
\end{tikzpicture}
\end{document}
Example of how label
changes which node is named in the matrix (instead of expanding the node):
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix,fit}
\begin{document}
\begin{tikzpicture}
\matrix (M) [matrix of nodes,%
row sep=1mm,%
nodes={draw, fill=gray!20,%
minimum width=.5cm, outer sep=0pt,%
minimum height=.7cm, anchor=center}
]%
{
|[label=left:1]| &[2mm] 2\\
|[label={[name=none]left:2}]|& 1\\
};
\foreach \i in {1,2}{
\draw[->] (M-\i-1)--(M-\i-2.west);
\node [fit=(M-\i-1),draw,red] {};
}
\end{tikzpicture}
As starting point, but now is complete image:
\documentclass[margin=3.141592]{standalone}
\usepackage{amssymb}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,
backgrounds,
chains,
positioning,
shapes.geometric, shapes.multipart
}
\begin{document}
\begin{tikzpicture}[%scale=.2,
node distance = 7mm and 4mm,
start chain = going right,
arr/.style = {semithick, -Stealth},
dot/.style = {circle, fill, inner sep=1.2pt,
label=left:#1},
every label/.append style = {font=\footnotesize, fill=white, align=center,
fill opacity=0.5, text opacity=1,
inner sep=1pt},
E/.style = {ellipse, draw, fill=#1},
mpnh/.style = {rectangle split, rectangle split horizontal,
rectangle split parts=3, draw, fill=gray!20,
inner sep=2pt,
on chain},
mpnv/.style = {rectangle split, rectangle split parts=10,
rectangle split part fill={gray!30,gray!10,gray!30,gray!30,gray!30,
gray!10,gray!30,gray!10,gray!10,gray!30},
draw, minimum height=2ex},
sym/.style = {yshift=-1mm},
syp/.style = {yshift=+1mm},
]
\node[mpnv, label=H] (H)
{\nodepart{one} $\diagup$
\nodepart{two} \vphantom{$\diagup$}
\nodepart{three} $\diagup$
\nodepart{four} $\diagup$
\nodepart{five} $\diagup$
\nodepart{six} \vphantom{$\diagup$}
\nodepart{seven} $\diagup$
\nodepart{eight} \vphantom{$\diagup$}
\nodepart{nine} \vphantom{$\diagup$}
\nodepart{ten} $\diagup$
};
%
\node[mpnh, right=of H.two east] (A1)
{\nodepart{one} $\diagup$
\nodepart{two} $k_1$
\nodepart{three} \hphantom{$\diagup$}
};
\node[mpnh] (A2)
{\nodepart{one} \hphantom{$\diagup$}
\nodepart{two} $k_4$
\nodepart{three} $\diagup$
};
%
\node[mpnh, right=of H.six east] (B1)
{\nodepart{one} $\diagup$
\nodepart{two} $k_5$
\nodepart{three} \hphantom{$\diagup$}
};
\node[mpnh] (B2)
{\nodepart{one} \hphantom{$\diagup$}
\nodepart{two} $k_2$
\nodepart{three} \hphantom{$\diagup$}
};
\node[mpnh] (B3)
{\nodepart{one} \hphantom{$\diagup$}
\nodepart{two} $k_7$
\nodepart{three} $\diagup$
};
%
\node[mpnh, right=of H.eight east] (C1)
{\nodepart{one} $\diagup$
\nodepart{two} $k_3$
\nodepart{three} $\diagup$
};
%
\node[mpnh, right=of H.nine east] (D1)
{\nodepart{one} $\diagup$
\nodepart{two} $k_8$
\nodepart{three} \hphantom{$\diagup$}
};
\node[mpnh] (D2)
{\nodepart{one} \hphantom{$\diagup$}
\nodepart{two} $k_6$
\nodepart{three} $\diagup$
};
%% arrows (right)
\draw[arr] (H |- H.two east) edge (A1)
(H |- H.six east) edge (B1)
(H |- H.eight east) edge (C1)
(H |- H.nine east) to (D1)
;
\draw[arr, transform canvas={yshift=1mm}]
(A1.three north |- A1.east) edge (A2)
(B1.three north |- B1.east) edge (B2)
(B2.three north |- B2.east) edge (B3)
(D1.three north |- D2) to (D2)
;
\draw[arr, transform canvas={yshift=-1mm}]
(A2.one north |- A2) edge (A1)
(B2.one north |- B2) edge (B1)
(B3.one north |- B3) edge (B2)
(D2.one north |- D2) to (D1)
;
%% dots, ellipses
\pgfmathsetseed{3}
Explicitly sets the seed for
\foreach \i in {1,2,...,8}
\node (k\i) [dot=$k_{\i}$] at (-33mm +40*rand,0.5*rand) {};
\scoped[on background layer]
{
\draw[fill=gray!30] (-4,0.4) ellipse (3 and 2);
\path (-4,1) node[label={$U$\\ (universe of keys)}] {};
\draw[fill=white] (-4,0) ellipse (2.4 and 1);
\path (-6,0) node[label=right:$K$\\ (actual\\ keys)] {};
\draw[arr] (k1) edge ([syp] H.two west)
(k4) edge ([sym] H.two west)
(k2) edge ([syp] H.six west)
(k5) edge (H.six west)
(k7) edge ([sym] H.six west)
(k3) edge (H.eight west)
(k8) edge ([syp] H.nine west)
(k6) edge ([sym] H.nine west)
;
}
\end{tikzpicture}
\end{document}
Best Answer
Arguably overkill, but here's a version using the TikZ libraries
shapes.multipart
,chains
andpositioning
:EDIT
In response to the comment asking about the addition of arcs, there are various options. Here are 4 different arcs in various colours for ease of identification. To please egreg, I assume that the thing which I read as the Greek letter phi is, in fact, intended to be an empty set.