5

Can anyone recommend any tutorial/library or just explain how can I draw this type of table, divided into few part with arrows? Like on this picture:

enter image description here

jub0bs
  • 58,916
Ziva
  • 651

1 Answers1

4

This solution uses the following packages:

  • forest (also etoolbox)

    forest is used to create the upper part of the tree, every node of this tree will use the algorithm behind the sort key. Every mirrored node will be placed at the orthogonal opposite of the last line. The edges of the lower part are rudimentary drawn with an edge path operator of TikZ (forest offers a few options for edges that are not used here).

  • expl3

    The expl3 package provides a sorting algorithm for lists.

  • xstring

    The xstring package provides a \StrSubstitute macro that first replaces all spaces to commas , for the sorting macro. The sorted result is then again thrown into \StrSubstitute to re-replace the commas to spaces.

Furthermore, the calc library from TikZ is used to place the sorted nodes at the other side (this could have been easily done without calc) as well as the PGFmath function strrepeat.

A similar approach for a calc-less positioning can be found in another answer of mine (look for Stern Brocot at and Stern Brocot at*). This is also the answer where I first used the strrepeat function.

This function is only used once to automatically create the name of the first child of the last level of the tree (here: 39) so that it can be used later as \forestOnes.
The sort level key also sets up the \forestSortLevel macro so that it can be used inside the sort key.

Possible improvements

  • Getting the maximum level directly from forest and not from the user.
  • Sorting with spaces without the need to replace the spaces (or maybe a LaTeX3 solution for the replacing).
  • Automatic splitting of a list of numbers by forest so that one does only need to add the root node.
  • Exploiting something like execute at end picture but for forest for the lower part of the tree. The sort key is actually executed before anything is drawn (and outside of TikZ) which is the reason that all \nodes (and their edges) are saved in \forestSortedNodes. The same is true for the \coordinate call which just as well should be setup by sort level.

Code

\documentclass[tikz]{standalone}
\usepackage{forest,expl3,xstring}
\usetikzlibrary{arrows.meta}
\makeatletter
\pgfmathdeclarefunction{strrepeat}{2}{%
  \begingroup
    \pgfmathint@{#2}%
    \pgfmath@count\pgfmathresult
    \let\pgfmathresult\pgfutil@empty
    \pgfutil@loop
      \ifnum\pgfmath@count>0\relax
      \expandafter\def\expandafter\pgfmathresult\expandafter{\pgfmathresult#1}%
      \advance\pgfmath@count-1\relax
    \pgfutil@repeat
    \pgfmath@smuggleone\pgfmathresult
  \endgroup}
\makeatother
\ExplSyntaxOn
\newcommand*\sortList[1]{
  \clist_sort:Nn #1 {
    \int_compare:nNnTF {##1} > {##2}
      \sort_return_swapped:
      \sort_return_same:
  }
}
\ExplSyntaxOff
\forestset{
  sort/.code={%
    \pgfmathparse{level()>\forestSortLevel}%
    \ifnum\pgfmathresult=0
      % sort content of node
      \StrSubstitute{\forestov{content}}{ }{,}[\myList]%
      \sortList\myList
      \StrSubstitute{\myList}{,}{ }[\myList]%
      % add corresponding node on the other side of the tree
      \pgfmathparse{strrepeat("1",level())}%
      \xappto\forestSortedNodes{%
        \noexpand\node at ($(\forestov{name}|-m)!-1!(\forestov{name})$)
        (m\forestov{name}) {\myList}}%
      % add edges
      % edges to original forest tree
      \pgfmathparse{level()==\forestSortLevel}%
      \ifnum\pgfmathresult=1
        % \forestFirst=\forestLast? only on parent (the 10 in this example)
        \forestOget{\forestov{@first}}{name}\forestFirst
        \forestOget{\forestov{@last}}{name}\forestLast
        \xappto\forestSortedNodes{{%
          [<-] edge (\forestOv{\forestov{@first}}{name})
            \ifx\forestFirst\forestLast\else edge
            (\forestOv{\forestov{@last}}{name})\fi
          }}%
      \fi
      % eges to original forest tree
      \ifnum\forestov{@parent}=0\else
        \xappto\forestSortedNodes{edge (m\forestOv{\forestov{@parent}}{name})}%
      \fi
      \gappto\forestSortedNodes{;}%
    \fi}}
\forestset{
  sort level/.code=%
    \def\forestSortedNodes{}%
    \pgfmathsetmacro\forestSortLevel{#1}%
    \pgfmathsetmacro\forestOnes{strrepeat("1",\forestSortLevel+1)}%
}
\begin{document}
\begin{forest} 
  /tikz/arrows=->, /tikz/>=Latex, %/tikz/nodes={draw},
  for tree={delay={sort}}, sort level=2
[38 27 43 3 9 82 10
  [38 27 43 3
    [38 27 [39][27]]
    [43 3 [43][3]]
  ]
  [9 82 10
    [9 82 [9] [82]]
    [10 [10]]
  ]
]
%
\coordinate (m) at (!|-!\forestOnes);
\forestSortedNodes
\end{forest}
\end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821