有人可以推荐任何教程/库,或者只是解释如何绘制这种类型的表格,用箭头分成几个部分吗?喜欢这张照片:
答案1
该解决方案使用以下软件包:
-
forest
用于创建树的上部,该树的每个节点都将使用密钥背后的算法sort
。每个m
镜像节点都将放置在最后一条线的正交对面。下部的边缘是使用edge
TikZ 的路径运算符初步绘制的(forest
为此处未使用的边缘提供了一些选项)。 -
该
expl3
包提供了列表的排序算法。 -
该
xstring
包提供了一个\StrSubstitute
宏,它首先将排序宏中的所有空格替换为逗号
,
。然后再次将排序后的结果放入其中,\StrSubstitute
将逗号重新替换为空格。
此外,calc
TikZ 的库用于将已排序的节点放置在另一侧(这在没有的情况下也可以轻松完成calc
)以及 PGFmath 函数strrepeat
。
对于 a -less 定位的类似方法calc
可以在我的另一个答案(寻找Stern Brocot at
和Stern Brocot at*
)。这也是我第一次使用该函数的答案strrepeat
。
此函数仅使用一次,用于自动创建树最后一级的第一个子项的名称(此处:),39
以便稍后将其用作\forestOnes
。
密钥sort level
还设置了\forestSortLevel
宏,以便可以在sort
密钥内部使用。
可能的改进
forest
直接从用户而不是从用户那里获取最高级别。- 使用空格排序而无需替换空格(或者可能是用于替换的 LaTeX3 解决方案)。
- 自动拆分数字列表,
forest
以便只需添加根节点。 - 利用类似
execute at end picture
但用于forest
树下部的东西。sort
键实际上是在绘制任何内容之前执行的(并且在 TikZ 之外),这就是所有\node
s(及其边缘)都保存在 中的原因\forestSortedNodes
。 对于 调用也是如此\coordinate
,它也应该由 来设置sort level
。
代码
\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}