TransWikia.com

How should I draw a linked list each node pointed by additional node

TeX - LaTeX Asked on August 11, 2021

I would like draw a linked-list example as on the following figure. Idea is similiar to solution for How should I draw a singly/double linked list?, but I wasn’t able to do the arrowing from north node to south node.

enter image description here

I have used following example for How to make a graph (nodes and edges) on Latex? .

  • I was not able to put the labes next to boxes, followed by a dash to point them. Also dashed rectangle that covers the three boxes at top.

Minimal code that I tried:

documentclass[tikz,margin=3]{standalone}
usetikzlibrary{shadows} % Shadows for nodes
begin{document}
begin{tikzpicture}
  tikzset{% This is the style settings for nodes
    dep/.style={square,minimum size=1cm,fill=orange!20,draw=orange,
      general shadow={fill=gray!60,shadow xshift=1pt,shadow yshift=-1pt}},
    cli/.style={square,minimum size=1cm,fill=white,draw,
      general shadow={fill=gray!60,shadow xshift=1pt,shadow yshift=-1pt}},
    spl/.style={square,append after command={
        node[circle,draw,dotted,
        minimum size=1.5cm] at (tikzlastnode.center) {}}},
    c1/.style={-stealth,very thick,black!80!black},
    v2/.style={-stealth,very thick,yellow!65!black},
    v4/.style={-stealth,very thick,purple!70!black}}
  node[dep] (1) at (0,0) {0};
  node[dep] (2) at (2,0) {4};
  node[dep] (3) at (4,0) {10};
   %
  node[cli] (16) at (6,0) {tail};

  node[cli] (7) at (0,-2) {-16};
  node[cli] (8) at (2,-2) {-16};
  node[cli] (9) at (4,-2) {-16};
  %
  node[cli] (10) at (0,-3) {3};
  node[cli] (11) at (2,-3) {10};
  node[cli] (12) at (4,-3) {15};
  %
  node[dep] (13) at (0,-4) {4};
  node[dep] (14) at (2,-4) {10};
  node[cli] (15) at (4,-4) {/};

  draw[c1] (1) -- (7);
  draw[c1] (2) -- (8);
  draw[c1] (3) -- (9);
  draw[c1] (16) -- (3);
end{tikzpicture}
end{document}

3 Answers

Usually anything that looks like a matrix can be made more easily with a TikZ matrix. And usually a TikZ matrix is ​​easier than the cumbersome placement of single nodes.

1. The picture from the startpost:

enter image description here

documentclass[margin=5pt, tikz]{standalone}
usepackage{tikz}
usetikzlibrary{matrix}
begin{document}

begin{tikzpicture}[font=footnotesizesffamily,
>=stealth, 
]
matrix (m) [matrix of nodes,  nodes in empty cells,
nodes={draw, %thick, 
%inner sep=0pt,   outer sep=0pt,
%minimum width=1.9em,
text height=htstrutbox,
text depth=dpstrutbox,
text width =1.5htstrutbox,
align=center, anchor=center,
}, 
column sep=1em, row sep=-pgflinewidth,
Fill/.style 2 args={row #1 column #2/.style={nodes={fill=cyan!66}}},
Fill/.list={ {5}{2}, {5}{3} },
row 1/.style={nodes={draw=none}  },
column 1/.style={column sep=2em,
nodes={align=right, draw=none, text width=1cm}  },
%
row 2 column 1/.style={nodes={xshift=-2mm}},
%
column 5/.style={nodes={draw=none}  },
row 2 column 5/.style={nodes={draw}  },
%
row 2/.style={row sep=1.5em,   },
%
column 4/.style={column sep=1.75em,   },
]{
          &         &        &        &  tail   
mapping   &  0      &  4     &  10    & 10       
value     &  -16    &  -16   &  -16   &          
point     &  3      &  10    &  15    &           
next      &  4      &  10    &  /     &            
%1  &  2   &  3   &  4   &  5   
};

% Annotations:
foreach col in {2,...,4}{
draw[->] (m-2-col) -- (m-3-col);     }
draw[->] (m-2-5) -- (m-2-4);

foreach row in {3,...,5}{
draw[shorten >=2pt] (m-row-1) -- (m-row-2);     }

draw[shorten >=1em] (m-2-1) -- (m-2-2);     
    
draw[densely dashed] ([shift={(-0.5em,0.5em)}]m-2-2.north west) rectangle ([shift={(0.5em,-0.5em)}]m-2-lastcolP.south east);
end{tikzpicture}
end{document}

2. With variable numbers of rows and columns:

There is no key like row last/.style=... so you need to create them and then use some tricks due to the expanding order:

enter image description here

documentclass{article}
usepackage{tikz}
usetikzlibrary{matrix}
makeatletter
tikzset{store number of columns in/.style={execute at end matrix={
xdef#1{thepgf@matrix@numberofcolumns}}},
store number of rows in/.style={execute at end matrix={
xdef#1{thepgfmatrixcurrentrow}}}}
makeatother

begin{document}
% Wrong start values
deflastrow{1}
deflastcol{1}
deflastcolP{1}
newcommandmymatrix{%%%
begin{tikzpicture}[font=footnotesizesffamily,
>=stealth, 
]
matrix (m) [matrix of nodes,  nodes in empty cells,
store number of columns in=lastcol,
store number of rows in=lastrow,
ampersand replacement=&, 
nodes={draw, %thick, 
inner sep=0pt,   outer sep=0pt,
minimum width=1.9em,
text height=htstrutbox,
text depth=dpstrutbox,
text width =1.5htstrutbox,
align=center, anchor=center,
}, 
column sep=1em, row sep=-pgflinewidth,
]{
       &    &      &     &        &  tail   
mapping&  0 &  4   & new  &  1    &  10    
value  &  -16  &  -16 & new  &  -16  &   
point  &  3   &  10  & new   &  15   &     
new    & new  &  new   & new &  new  &       
new    & new  &  new   & new &  new  &       
new    & new  &  new   & new &  new  &       
next   &  4      &  10       & new     &  /  &   
%1  &  2   &  3   &  4   &  5   & 6 
};
%
% Annotations:
foreach col in {2,...,lastcolP}{
draw[->] (m-2-col) -- (m-3-col);     }
draw[->] (m-2-lastcol) -- (m-2-lastcolP);

foreach row in {3,...,lastrow}{
draw[shorten >=2pt, shorten <=2pt] (m-row-1) -- (m-row-2);     }

draw[shorten >=0.7em, shorten <=3pt] (m-2-1) -- (m-2-2);     

draw[densely dashed] ([shift={(-0.5em,0.5em)}]m-2-2.north west) rectangle ([shift={(0.5em,-0.5em)}]m-2-lastcolP.south east);
end{tikzpicture}
}%%%

newsavebox{mybox}
savebox{mybox}{mymatrix}

section{Wrong} 
mymatrix 

section{Still Wrong} 
usebox{mybox} par
Last col is: lastcol.  Last row is lastrow. 


pgfmathtruncatemacrolastcolP{lastcol-1}
tikzset{
store number of columns in=lastcol,
store number of rows in=lastrow,
Fill/.style 2 args={row #1 column #2/.style={nodes={fill=cyan!44}}},
Fill/.list={ {lastrow}{2}, {lastrow}{3} },
row 1/.style={nodes={draw=none}  },
column 1/.style={column sep=2em,
nodes={align=right, draw=none, text width=1cm}  },
%
row 2 column 1/.style={nodes={xshift=-2mm}},
%
column lastcol/.style={nodes={draw=none}  },
row 2 column lastcol/.style={nodes={draw}  },
%
row 2/.style={row sep=1.5em,   },
%
column lastcolP/.style={column sep=1.75em,   },
}

section{Correct} 
savebox{mybox}{mymatrix}
usebox{mybox}
end{document}

Correct answer by cis on August 11, 2021

Here you go, I'm using the positioning library to achieve it without a bunch of extra commands setting up coordinates.

Your code had an error with the square style; I removed the term `square' as it appears to not do anything to your code.

I've included the text above the tail box in case you wish to use it (as I see you've already written 'tail' inside the box).

enter image description here

documentclass[tikz,margin=3]{standalone}
usetikzlibrary{shadows, positioning} % Shadows for nodes
begin{document}
begin{tikzpicture}
  tikzset{% This is the style settings for nodes
    dep/.style={minimum size=1cm,fill=orange!20,draw=orange,
      general shadow={fill=gray!60,shadow xshift=1pt,shadow yshift=-1pt}},
    cli/.style={minimum size=1cm,fill=white,draw,
      general shadow={fill=gray!60,shadow xshift=1pt,shadow yshift=-1pt}},
    spl/.style={append after command={
        node[circle,draw,dotted,
        minimum size=1.5cm] at (tikzlastnode.center) {}}},
    c1/.style={-stealth,very thick,black!80!black},
    v2/.style={-stealth,very thick,yellow!65!black},
    v4/.style={-stealth,very thick,purple!70!black}}
  node[dep] (1) at (0,0) {0};
  node[dep] (2) at (2,0) {4};
  node[dep] (3) at (4,0) {10};
   %
  node[cli] (16) at (6,0) {tail};

  node[cli] (7) at (0,-2) {-16};
  node[cli] (8) at (2,-2) {-16};
  node[cli] (9) at (4,-2) {-16};
  %
  node[cli] (10) at (0,-3) {3};
  node[cli] (11) at (2,-3) {10};
  node[cli] (12) at (4,-3) {15};
  %
  node[dep] (13) at (0,-4) {4};
  node[dep] (14) at (2,-4) {10};
  node[cli] (15) at (4,-4) {/};

  draw[c1] (1) -- (7);
  draw[c1] (2) -- (8);
  draw[c1] (3) -- (9);
  draw[c1] (16) -- (3);
  
  % label lines next to boxes
  
  node[left = 0.3cm of 1] (labellineTop){};
  node[left = 0.3cm of 7] (labelline1){};
  node[left = 0.3cm of 10] (labelline2){};
  node[left = 0.3cm of 13] (labelline3){};
  
  draw (labelline1) -- +(-1,0);
  draw (labelline2) -- +(-1,0);
  draw (labelline3) -- +(-1,0);
  draw (labellineTop) -- +(-1,0);
  
  % labels next to boxes
  
  node[left = 1.5cm of 1, align=right] {mapping};
  node[left = 1.5cm of 7, align=right] {value};
  node[left = 1.5cm of 10, align=right] {point};
  node[left = 1.5cm of 13, align=right] {next};
  node[above = 0.2cm of 16] {tail};
  
  % dashed rectangle
  
  node[above left = 0.3cm of 1] (rectangleA){};
  node[below right = 0.3cm of 3] (rectangleB){};
  draw[dashed] (rectangleA) rectangle (rectangleB){};
  
end{tikzpicture}
end{document}

Answered by pikopiko on August 11, 2021

This is not really an answer but I agree with this answer by pikopiko that it is better not position anything by hand. So out of many possibilities that allow you to avoid manual positioning here is one using a matrix.

documentclass[tikz,margin=3]{standalone}
usepackage{sansmath}
usetikzlibrary{fit,matrix,positioning,shadows} 
begin{document}
begin{tikzpicture}[font=sffamilysansmath,
    square/.style={minimum size=1cm,draw,fill=white,drop shadow},
    f/.style={fill=orange!20,draw=orange},
    v2/.style={-stealth,very thick,yellow!65!black}]
 matrix[matrix of math nodes,row sep=-pgflinewidth,column sep=1.5em,
 cells={nodes={square,
    text depth=0.25ex,text height=1em}},
 row 1/.style={nodes=f}] (m){
  0 & 4 & 10 [2em]
  -16 & -16 & -16
  3 & 10 & 15
  |[f]|4 & |[f]|10 & /
 };
 %
 node[draw,dashed,inner sep=1em,fit=(m-1-1)(m-1-3)](f){};
 %
 node[square,right=3em of m-1-3] (t){tail};
 %
 foreach x[count=y] in {mapping,value,point,next}
 {draw ifnumy=1 (f.west)
 else
 (m-y-1.west)fi -- ++ (-2em,0) node[left]{x};}
 %
 draw[v2] (t) -- (m-1-3);
 foreach x in {1,2,3}
 {draw[v2] (m-1-x) -- (m-2-x);}
end{tikzpicture}
end{document}

enter image description here

Answered by user227987 on August 11, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP