3

I need to illustrate a linked list and the addition of one element is there any way I can stop and continue the foreach loop or pause the chain so it doesn't connect elements 5 and 6 for example?

\documentclass{article}
\usepackage{pgffor}
\usepackage{tikz}
\usepackage{xfp}
\usepackage{mathtools}
\usetikzlibrary{calc, shapes.multipart,chains,arrows,positioning}

\tikzstyle{strela} = [thick, ->, >=stealth]

\newcommand\x{9} \newcommand\y{3} \newcommand\m{5}

\begin{document}

\begin{tikzpicture}[ar/.style={*->,shorten <=-.28cm},list/.style={rectangle split, rectangle split parts=2, draw, rectangle split horizontal,join=by ar}, start chain=going right]


        \foreach \i in {3,...,\the\numexpr\x}{
            \node[list,on chain] (\the\numexpr\i) {\i};         
        }  
        \node (strela2) [strela, below of= 3,  xshift=-0.5cm, yshift=-0.7cm]{HEAD};
        \draw (strela2) -> (3); 

        \node (strela3) [strela, below of= \the\numexpr\x,  xshift=-0.5cm, yshift=-0.7cm] {TAIL};
        \draw (strela3) -> (\the\numexpr\x);

        \node (obj) [right of= \the\numexpr\x,draw,inner sep=6pt] (D) {};
        \draw (D.north east) -- (D.south west);
        \draw (D.north west) -- (D.south east);

        \draw [*->, shorten <=+.10cm] (\the\numexpr\x.center) -- (D);

        \node (strela5) [strela, below of= D, yshift=-0.72cm] {NULL};
        \draw (strela5) -> (D);

  \node[list,below of= \the\numexpr\m, xshift=+1cm] (A) {\the\numexpr\m+0.5};



\end{tikzpicture}

\begin{flushleft}
    \vspace{2cm}        

\end{flushleft}

\begin{tikzpicture}[ar/.style={*->,shorten <=-.28cm},list/.style={rectangle split, rectangle split parts=2, draw, rectangle split horizontal,join=by ar}, start chain=going right]


\foreach \i in {3,...,\the\numexpr\x/2}{
    \node[list,on chain] (\the\numexpr\i) {\i};         
} 


\node[list,below of= \the\numexpr\m, xshift=+1cm] (A) {\the\numexpr\m+0.5};


\draw[*->] let \p1 = (\the\numexpr\m.two), \p2 = (\the\numexpr\m.center) in (\x1,\y2) -- (A);

\draw[*->] let \p1 = (A.two), \p2 = (A.center) in (\x1,\y2) -- (\the\numexpr\m+1);


\foreach \k in {\the\numexpr\x/2 + 1,...,\the\numexpr\x}{
\node[list, on chain] (\the\numexpr\i) {\k};            

}

\node (strela2) [strela, below of= 3,  xshift=-0.5cm, yshift=-0.7cm]{HEAD};
\draw (strela2) -> (3); 

\end{tikzpicture} \end{document}

egreg
  • 1,121,712

2 Answers2

3

You could test for the current number and add the connection based on this test.

Unrelated to your question: don't use the deprecated \tikzstyle, you can use \tikzset instead.

\documentclass{article}
\usepackage{pgffor}
\usepackage{tikz}
\usepackage{xfp}
\usepackage{mathtools}
\usetikzlibrary{calc, shapes.multipart,chains,arrows,positioning}

\tikzset{strela/.style={thick, ->, >=stealth}}

\newcommand\x{9} \newcommand\y{3} \newcommand\m{5}

\begin{document}

\begin{tikzpicture}[ar/.style={*->,shorten <=-.28cm},list/.style={rectangle split, rectangle split parts=2, draw, rectangle split horizontal}, start chain=going right]


        \foreach \i in {3,...,\the\numexpr\x}{
          \ifnum\i=6
            \node[list,on chain] (\the\numexpr\i) {\i};
          \else
            \node[list,on chain,join=by ar] (\the\numexpr\i) {\i};         
          \fi
        }  


\end{tikzpicture}


\end{document}

enter image description here

3

Solution 1

\foreach \i in {3, ..., 9}
  \node[list, on chain,
    /utils/TeX/ifnum={\i=6}{}{join=by ar}
  ] {\i};

is similar to samcarter's answer it just moves the \ifnum inside the options of the node so that you don't have to write redundant code.

Without ext.misc you could do for almost the same effect

\node[list, on chain, style/.expanded={\ifnum\i=6 \else join=by ar\fi}] {\i};

but it's a bit messy.

With an ar* style defined as

ar*/.style={
  to path={[insert path/.expanded={
      edge[path only, line to]
        node[list,below=5mm] (@) {\unexpanded{#1}} (\tikztotarget)
      (\tikztostart) edge[ar] (@)
      (@) edge[ar] (\tikztotarget)}]}}

you can do

\node[list, on chain,
  /utils/TeX/ifnum={\i=6}{join=by {ar*={5,5}}}{join=by ar}
] {\i};

and even get

enter image description here

without much work (though, I'd suggest adding text depth=0pt to the list style).


Solution 2 just tries a few styles which might disable the join key. This also which means that join?=\i (or just kill join \i/.try) needs to come before the actual join key. (Unfortunately, there is no “clean” way to unjoin a node but this seems simple enough.)

The .list handler allows you do quickly give a list of \i it shouldn't join.

Adding ar* connections instead is probably similarly possible just with a very specific \i dependent key.

Code

\documentclass[varwidth]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc, shapes.multipart, chains, arrows.meta}
\tikzset{every picture/.append style={
  node distance=5mm,
  */.tip={Circle[sep=-1.196825pt -1.595769]},
  ar/.style={*->, to path={($(\tikztostart.two south)!.5!(\tikztostart.two north)$) -- (\tikztotarget)}},
  ar*/.style={
    to path={[insert path/.expanded={
        edge[path only, line to]
          node[list,below=5mm] (@) {\unexpanded{##1}} (\tikztotarget)
        (\tikztostart) edge[ar] (@)
        (@) edge[ar] (\tikztotarget)}]}},
  list/.style={rectangle split, rectangle split parts=2, draw, rectangle split horizontal},
  start chain=going right}}

% Solution 1: \usetikzlibrary{ext.misc}

% Solution 2: \tikzset{ join?/.style={kill join on #1/.try}, don't join on/.style={ kill join on #1/.style={join/.code=}}}

\begin{document} % Solution 1: \tikz\foreach \i in {3, ..., 9} \node[list, on chain, /utils/TeX/ifnum={\i=6}{join=by {ar*={5,5}}}{join=by ar} ] {\i}; \

% Solution 1 without ext.misc \tikz\foreach \i in {3, ..., 9} \node[list, on chain, style/.expanded={\ifnum\i=6 \else join=by ar\fi}] {\i}; \

% Solution 2: \tikz[don't join on=6]\foreach \i in {3, ..., 9} \node[list, on chain, join?=\i, join=by ar] {\i}; \

% Solution 2 with more than one: \tikz[don't join on/.list={4,6,8}]\foreach \i in {3, ..., 9} \node[list, on chain, join?=\i, join=by ar] {\i}; \end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821