3

I'm using rectangle split to draw link nodes:

enter image description here

How to ensure every rectangle split with the same size, especially with the same width! no matter it is empty or with one digit or with two digits (maximum two digits, or like "-1")

MWE(my code):

\documentclass[border=10pt]{standalone}
\usepackage{tikz, tkz-graph}
\usetikzlibrary{arrows,positioning}
\thispagestyle{empty}
\usepackage{memorygraphs}
\tikzset{
    phead/.style={
           rectangle, draw, text height=3mm, text width=3mm,
       text centered, node distance=3cm, inner sep=0pt
    },
    block/.style={
            draw,
            %text height=height("I"),
            %text depth=depth("I"),
            anchor=mid,
            %inner sep=0pt,
            %minimum width=0.6cm,
            every block,
    },
    arity/.style={
        block,
        rectangle split,
        rectangle split parts=#1+1,
        rectangle split horizontal,
        rectangle split every empty part={},
        rectangle split empty part width=0.6cm,
        minimum size=0.6cm,
    }   
}
\begin{document}
\begin{tikzpicture}[memory graph]

\node[phead, label=above:head] (head) {};

\def\prevname{head}
\foreach \name/\labela/\val in {1/7/,2/7/,3//,4/12/,5/13/,6/0/-1}{
    \ifnum \name=1
        \node[block,arity=1,right=of \prevname] (a\name) {\labela};
        \draw[ref] (\prevname.center) -- (a\name);
    \else
        \node[block,arity=1,right=of \prevname.arg 1 east] (a\name) {\labela};
        \draw[ref] (\prevname.arg 1 center) -- (a\name);
    \fi
    
    
    \xdef\prevname{a\name}
}

\end{tikzpicture}
\end{document}

You can see I've override some tikz style of the memorygraphics in the code above, like block and arity

Some code(style) of package memeorygraphics: https://ctan.org/pkg/memorygraphs

\tikzset{
    memory graph/.style={
        node distance=1.5em,
    },
    every block/.style={},
    block/.style={
        draw,
        text height=height("I"),
        text depth=depth("I"),
        anchor=mid,
        every block,
    },
    block/.append code={%
        \let\arg\memorygraphs@arg%
        \gdef\memorygraphs@arity{0}%
    },
    block mark north east/.style={
        append after command={
            \pgfextra
                \pgfinterruptpath
                \draw[#1]
                    ($(\tikzlastnode.head north east)-(\ifnum\memorygraphs@arity=0 .5\pgflinewidth\else0\fi,.5\pgflinewidth)$)
                    -- +(0,-\memorygraphs@marklength)
                    -- ($(\tikzlastnode.head north east)-(\ifnum\memorygraphs@arity=0 .5\pgflinewidth\else0\fi+\memorygraphs@marklength,.5\pgflinewidth)$)
                    -- cycle;
                \endpgfinterruptpath
            \endpgfextra
        },
    },
    block mark south east/.style={
        append after command={
            \pgfextra
                \pgfinterruptpath
                \draw[#1]
                    ($(\tikzlastnode.head south east)+(\ifnum\memorygraphs@arity=0 -.5\pgflinewidth\else0\fi,.5\pgflinewidth)$)
                    -- +(0,\memorygraphs@marklength)
                    -- ($(\tikzlastnode.head south east)+(\ifnum\memorygraphs@arity=0 -.5\pgflinewidth\else0\fi-\memorygraphs@marklength,.5\pgflinewidth)$)
                    -- cycle;
                \endpgfinterruptpath
            \endpgfextra
        },
    },
    block mark north west/.style={
        append after command={
            \pgfextra
                \pgfinterruptpath
                \draw[#1]
                    ($(\tikzlastnode.head north west)+(.5\pgflinewidth,-.5\pgflinewidth)$)
                    -- +(0,-\memorygraphs@marklength)
                    -- ($(\tikzlastnode.head north west)-(-.5\pgflinewidth-\memorygraphs@marklength,.5\pgflinewidth)$)
                    -- cycle;
                \endpgfinterruptpath
            \endpgfextra
        },
    },
    block mark south west/.style={
        append after command={
            \pgfextra
                \pgfinterruptpath
                \draw[#1]
                    ($(\tikzlastnode.head south west)+(.5\pgflinewidth,.5\pgflinewidth)$)
                    -- +(0,\memorygraphs@marklength)
                    -- ($(\tikzlastnode.head south west)+(.5\pgflinewidth+\memorygraphs@marklength,.5\pgflinewidth)$)
                    -- cycle;
                \endpgfinterruptpath
            \endpgfextra
        },
    },
    arity/.style={
        block,
        rectangle split,
        rectangle split parts=#1+1,
        rectangle split horizontal,
        rectangle split every empty part={},
        rectangle split empty part width=.2em,
    },
    arity/.append code={%
        \pgfmathsetcount\c@pgf@counta{\pgfkeysvalueof{/pgf/rectangle split parts}}%
        \ifnum\c@pgf@counta=0\else\advance\c@pgf@counta by-1 \fi
        \xdef\memorygraphs@arity{\the\c@pgf@counta}%
    },
  ref/.style={
        {Circle[length=3pt]}-Latex,
        shorten <=-1.5pt,
        rounded corners=.2em,
    },
}

2 Answers 2

2

Small variation of nice @Peter Grill answer (+1) with pure tikz, i.e.: without memorygraphs package:

\documentclass[border=10pt]{standalone}
\usepackage{calc}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,
                chains,
                positioning,
                shapes.multipart}

\newlength\MinimumWidth
\setlength{\MinimumWidth}{\widthof{00}}
\tikzset{
arr/.style={{Circle[length=2pt 4, sep=0pt -4]}-Stealth},
arity/.style={
        rectangle split,
        rectangle split parts=#1+1,
        rectangle split horizontal,
        minimum height=10pt,
        rectangle split empty part width=\MinimumWidth-\pgfkeysvalueof{/pgf/inner xsep},
        text width=\MinimumWidth, align=center,
        execute at end node=\vphantom{fg},
        draw,
        on chain},
box/.style = {draw, text width=#1, minimum size=#1, inner sep=0pt},
box/.default = 4mm
        }
        
\begin{document}
    \begin{tikzpicture}[
node distance = 8mm and 7mm,
  start chain = on chain,
                        ]
\node[arity=0, box, label=head] (a0) {};
\foreach \labela/\val [count=\i from 0, count=\j] in {7/,7/,/,12/,13/,0/}%
{
\node[arity=1] (a\j) {\labela};
\draw[arr] (a\i.two north |- a\i.east) -- (a\j);
}

\node[arity=0, box, label=head,
      below=of a0] (b0) {};
\foreach \labela/\val [count=\i from 0, count=\j] in {17/,27/,/,2/,3/,0/}%
{
\node[arity=1] (b\j) {\labela};
\draw[arr] (b\i.two north |- b\i.east) -- (b\j);
}
\end{tikzpicture}
\end{document}

enter image description here

Edit: Removed are colors of nodes borders, now all nodes' parts has equal width and height.

7
  • Thanks! beautiful solution! Could you please give a demo of vertical rectangle split? like this: ![](img-blog.csdnimg.cn/5f49b5265aa4449da76582c835aef7e9.png)
    – xaero
    Mar 23, 2022 at 12:08
  • If you have new problem, please ask new question. In principle you need in my answer remove code line rectangle split horizontal, and accordingly draw arrows.
    – Zarko
    Mar 23, 2022 at 12:42
  • tex arityv/.style={ rectangle split, rectangle split parts=#1+1, rectangle split every empty part={}, rectangle split empty part height=height("I"), minimum height=6mm, text height=height("I"), text width=\MinimumWidth, align=center,% <--- NOTE draw, on chain}, box/.style = {draw, text width=#1, minimum size=#1, inner sep=0pt}, box/.default = 4mm }
    – xaero
    Mar 23, 2022 at 14:18
  • I've open a new issue, please have a look: tex.stackexchange.com/questions/638146/…
    – xaero
    Mar 23, 2022 at 14:27
  • Another question: How to modify the node distance between b2 and b3? (and others distance remain unchanged)
    – xaero
    Mar 24, 2022 at 7:57
2

Define a length of the width you desire. Here I set it to the width of two digits 00:

\newlength\MinimumWidth
\setlength{\MinimumWidth}{\widthof{00}}

and then apply

text width=\MinimumWidth, align=center,

The two different widths of the text yield same width rectangles:

enter image description here

Code:

\documentclass[border=10pt]{standalone}
\usepackage{tikz, tkz-graph}
\usetikzlibrary{arrows,positioning}
\thispagestyle{empty}
\usepackage{memorygraphs}
\usepackage{calc}

\pagecolor{white}

\newlength\MinimumWidth
\setlength{\MinimumWidth}{\widthof{00}}
\tikzset{
    phead/.style={
           rectangle, draw, text height=3mm, text width=3mm,
       text centered, node distance=3cm, inner sep=0pt
    },
    block/.style={
            draw,
            %text height=height("I"),
            %text depth=depth("I"),
            anchor=mid,
            %inner sep=0pt,
            %minimum width=0.6cm,
            every block,
    },
    arity/.style={
        block,
        rectangle split,
        rectangle split parts=#1+1,
        rectangle split horizontal,
        rectangle split every empty part={},
        rectangle split empty part width=0.6cm,
        minimum height=0.6cm,
        text width=\MinimumWidth, align=center,% <--- NOTE
    }   
}
\begin{document}
\begin{tikzpicture}[memory graph]

\node[phead, label=above:head] (head) {};

\def\prevname{head}
\foreach \name/\labela/\val in {1/7/,2/7/,3//,4/12/,5/13/,6/0/-1}{
    \ifnum \name=1
        \node[block,arity=1,right=of \prevname, red] (a\name) {\labela};
        \draw[ref] (\prevname.center) -- (a\name);
    \else
        \node[block,arity=1,right=of \prevname.arg 1 east, blue] (a\name) {\labela};
        \draw[ref] (\prevname.arg 1 center) -- (a\name);
    \fi
    \xdef\prevname{a\name}
}

\end{tikzpicture}
\begin{tikzpicture}[memory graph]

\node[phead, label=above:head] (head) {};

\def\prevname{head}
\foreach \name/\labela/\val in {1/17/,2/27/,3//,4/2/,5/3/,6/0/-1}{
    \ifnum \name=1
        \node[block,arity=1,right=of \prevname, red] (a\name) {\labela};
        \draw[ref] (\prevname.center) -- (a\name);
    \else
        \node[block,arity=1,right=of \prevname.arg 1 east, blue] (a\name) {\labela};
        \draw[ref] (\prevname.arg 1 center) -- (a\name);
    \fi
    \xdef\prevname{a\name}
}

\end{tikzpicture}
\end{document}
1
  • Text width controls the width of box? minimum size didn't work?
    – xaero
    Mar 23, 2022 at 12:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .