3

I want use Tikz to create linked lists (the data structures, with info and next fields in each node). The lists are horizontal, i.e., each node to the right of the previous one.

But some nodes must be placed slightly above or below the main path. See an example:

linked list

I'm currently using something similar to (next)-- ++(0.7, 0) |- (node) to draw the arrow from one node to the next, but I have to manage the distances manually.

Perhaps I'm missing a "build in" way in Tikz to connect the nodes the way I need. Or must I take care of the calculations myself?

Just expecting to not have to recode something that already exists...

3
  • I see I can use a different approach than my current one. However the distances in the examples are hardcoded, so I guess I have to make some calculation myself. Great insights in the manual! – Jander Mar 11 at 13:40
  • 1
    With the calc tikzlibrary you can use (next) -| ($(next)!.5!(node)$) |- (node) etc. – John Kormylo Mar 12 at 4:43
6

You can let TikZ do these things, regardless of whether you have positioned the nodes by hand or via a chain. You only need to dial some appropriate to path. The important ingredient in this example is \ifdim\n1>2pt, which changes the path depending on whether or not the levels of start and target are (roughly) the same. \n1 is the vertical distance, which has been measured with calc. Obviously you can do many similar tests to make things automatic.

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{arrows.meta,calc,chains,shapes.multipart}
\begin{document}
\begin{tikzpicture}[2p/.style={rectangle split,rectangle split horizontal,
    rectangle split parts=2,rectangle split part fill={none,gray!50},draw},
    hconnect/.style={semithick,{Circle[width=2pt,length=2pt]}-Stealth,to path={
        let \p1=($(\tikztotarget)-(\tikztostart)$),\n1={abs(\y1)},
         \n3={min(abs(\y1/2),2pt)}
         in
        \ifdim\n1>2pt
         (\tikztostart.two east-|\tikztostart.two south)[rounded corners=\n3] 
         -| ($(\tikztotarget)!0.5!(\tikztostart)$) |- (\tikztotarget) 
        \else
         (\tikztostart.two east-|\tikztostart.two south) -- (\tikztotarget) 
        \fi
    }}]
 \begin{scope}[yshift=2cm]  
  \node[2p](A){~10~~};  
  \node[2p,right=2em of A](B){~20~~};   
  \node[2p,right=2em of B,yshift=1em](C){~30~~};    
  \draw[hconnect] (A) to (B);
  \draw[hconnect] (B) to (C);
 \end{scope}
 %
 \begin{scope}[start chain=B going right,
    nodes={2p,on chain,join=by hconnect}]
  \path node{~10~~} node{~20~~} node[yshift=1em]{~30~~} 
    node[yshift=-1em]{~40~~} node{~50~~} node{~60~~};
 \end{scope}
 \path (B-6.two east-|B-6.two south) 
    node[circle,draw,inner sep=1.5pt,path picture={
    \draw(path picture bounding box.north east) -- 
        (path picture bounding box.south west);}]{};
\end{tikzpicture}
\end{document}

enter image description here

2
  • 2
    +1 That's a very comprehensive and well executed answer. Congratulations. – SebGlav Mar 11 at 17:36
  • That's great. I am not familiar to chains yet... a lot to learn. Thanks. – Jander Mar 11 at 18:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.