我能够使用下面的 MWE 生成以下树。它使用命令创建 tikzpictures\drawtape
并将它们放入保存框中,而保存框又可以直接用作环境中节点的内容forest
。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\newcommand{\drawtape}[3]{
\begin{tikzpicture}[cell/.style={minimum size=0.5cm,outer sep=0pt,draw,rectangle,node distance=0pt,text height=1.5ex}]
\foreach \x [count=\xi] in {#1} {
\ifnum \xi=1
\node[cell] (\xi) {$\x$};
\else
\pgfmathtruncatemacro{\xil}{\xi - 1}
\node[cell] (\xi) [right=of \xil] {$\x$};
\fi
}
\node[font=\footnotesize] [below=0cm of #2, xshift=0.03em] {$#3$};
\end{tikzpicture}
}
\newsavebox{\treeroot}
\newsavebox{\treeone}
\newsavebox{\treetwo}
\usepackage{forest}
\begin{document}
\savebox{\treeroot}{\drawtape{1, 1, 1}{1}{1}}
\savebox{\treeone}{\drawtape{0, 1, 1, 1}{1}{2}}
\savebox{\treetwo}{\drawtape{1, 1, 1}{2}{1}}
\begin{forest}
[\usebox{\treeroot}
[\usebox{\treeone}]
[\usebox{\treetwo}]
]
\end{forest}
\end{document}
对于像图中这样的小树来说,这没问题,但如果我想创建更大的树,那么我必须手动创建的保存箱数量很快就会变得非常繁琐。理想情况下,我希望能够编写一个forest
像下面这样的环境。有什么办法可以实现这一点吗?
\begin{forest}
[\drawtape{1, 1, 1}{1}{1}
[\drawtape{0, 1, 1, 1}{1}{2}]
[\drawtape{1, 1, 1}{2}{1}]
]
\end{forest}
答案1
如果您愿意考虑使用稍微不同的语法,您可以使用简单的表格以及append after command
。
\documentclass{article}
\usepackage{array}
\newcolumntype{C}[1]{>{\centering\arraybackslash}p{#1}}
\usepackage{forest}
\tikzset{drawtape/.style n args={3}{node contents={
\begin{tabular}{|*{10}{@{}C{5mm}@{}|}}
\hline
#1
\hline
\end{tabular}},append after command={
([xshift=#2*5mm-1mm]\tikzlastnode.south west)
node[anchor=north,inner sep=0pt,font=\footnotesize]{#3}}}}
\begin{document}
\begin{forest}
for tree={l sep+=2ex,edge={shorten <=2.5ex}}
[,drawtape={1& 1& 1\\}{1}{1}
[,drawtape={0 & 1 & 1& 1\\}{1}{2}]
[,drawtape={1& 1& 1\\}{3}{1}]
]
\end{forest}
\end{document}
答案2
感谢 Zarko 向我指出使用多部分节点,我得出了以下解决方案:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart, positioning}
\usepackage{xinttools}
\usepackage{forest}
\def\numname#1{%
\ifcase#1 \or one\or two\or three\or four\or five\or six\or seven\or eight\or nine\or ten\or eleven \or twelve\or thirteen\or fourteen\or fifteen\or sixteen\or seventeen\or eighteen\or nineteen\or twenty\fi%
}
\newcounter{cellnum}
\newcommand{\tape}[1]{%
\setcounter{cellnum}{1}
\xintFor* ##1 in {#1} \do {%
\nodepart[text width=1.5ex, align=center]{\numname{\value{cellnum}}} $##1$%
\stepcounter{cellnum}%
}
\addtocounter{cellnum}{-1}%
}
\begin{document}
\begin{forest}
for tree={
delay={
content={\tape{#1}}
},
rectangle split,
rectangle split horizontal,
rectangle split parts=\value{cellnum},
rectangle split part align=base,
draw,
l sep=6ex,
s sep=2em,
anchor=parent,
edge path={
\noexpand\path[draw]
([yshift=-2.5ex]!u.children) -- ([yshift=1ex].parent);
},
head/.style n args=2{
tikz={\node[below=0cm of .\numname{#1} south, font=\scriptsize]{$#2$};}
}
}
[111, head={1}{1}
[0111, head={1}{2}]
[111, head={2}{1}]
]
\end{forest}
\end{document}
不幸的是,边缘路径长度不等存在问题。我会寻求解决方案,并在找到解决方案后更新此答案。编辑:使用anchor=parent
infor tree
解决了这个问题。