Some time ago I found the question Draw an adjacency-list representation of a graph with tikz and wanted to solve it. I could but with some problems which still remain and How should I draw a singly/double linked list? remind me them.
My solution was:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix,arrows}
\begin{document}
\begin{tikzpicture}[>=stealth]
\matrix (M) [matrix of nodes,%
column sep=0pt,%
row sep=1mm,%
nodes={draw, fill=gray!20,%
minimum width=.5cm, outer sep=0pt,%
minimum height=.7cm, anchor=center},
column 1/.style={minimum height=.8cm}]%
{
\mbox{} &[2mm] 2 & \mbox{} &[2mm] 5 & / &[2mm] & &[2mm] & \\
\mbox{} & 1 & \mbox{} & 5 & \mbox{} & 3 & \mbox{} & 4 & / \\
\mbox{} & 2 & \mbox{} & 5 & \mbox{} & 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=0pt,%
row sep=1mm,%
nodes={draw, fill=gray!20,%
minimum width=.5cm, outer sep=0pt,%
minimum height=.7cm, anchor=center},
column 1/.style={minimum height=.8cm}]%
{
|[label=left:1]| \mbox{} &[2mm] 2 &\mbox{}&[2mm] 5 & / &[2mm] & &[2mm] & \\
|[label=left:2]|\mbox{} & 1 & \mbox{} & 5 & \mbox{} & 3 & \mbox{} & 4 & / \\
|[label=left:3]| \mbox{} & 2 & \mbox{} & 5 & \mbox{} & 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);
\end{scope}
\end{tikzpicture}
\end{document}
with this results
Now some questions:
1- I used \mbox{} to distinguish 'empty nodes' from 'empty cells'. Do you know a better solution?
2- Although column 1/.style
is declared boxes from 1st column show same heigth than other ones. Why?
3- Using labels
within nodes (bottom example) changes node
(or cell
?) center. This problem can be avoided with late options
(upper example). Do you know a better option?
4- Looking at first and secon column from upper example it seems that node's name is not equivalent to node.center. Do you know why?
5- I don't know if it's a rendering problem but it looks like adjacent cells have a thicker separation line. What must be column separation to draw border lines one over the other?
6- Solution for How should I draw a singly/double linked list? show starting point of *->
arrows aligned with node center, but here its beahviour is like in Modifying *
and o
style tikz arrows so that they are centered at the end of line. Coul you explain me why?
Best Answer
{}
instead of\mbox{}
to save yourself some typing when creating empty nodes. As ipavlic points out in his comment, you can also use thenodes 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.column 1/.style={nodes={minimum height=0.8cm}}
to change the node behaviour. If you don't usenodes=...
, 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).M-1-1
). You can prevent this by adding the optionevery 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 ofx
, but from the border ofx
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 usingshorten < = -2pt
.Here's your code with the suggested changes:
Example of how
label
changes which node is named in the matrix (instead of expanding the node):