我尝试了几种方法但还是无法找到可行的解决方案。
假设我使用 forest 包构建了这棵非常简单的树:
\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage{forest}
\begin{document}
\begin{forest}
for tree={circle,draw,s sep=0.8cm}
[$\lambda$
[,{edge label={node[midway,left] {B}}},{text=white,fill=black}
[,{edge label={node[midway,left] {A}}}
[,{edge label={node[midway,left] {B}}}
[,{edge label={node[midway,left] {A}}},
{text=white,fill=black}]
]
]
]
[,{edge label={node[midway,right] {A}}}
[,{edge label={node[midway,right] {B}}},
{text=white,fill=black}
[,{edge label={node[midway,right] {A}}},
{text=white,fill=black}]
]
]
]
\end{forest}
\end{document}
它看起来像这样:
我想在两个不同分支的节点之间画一个向后的箭头。使用 forest 包是否可行(因为从技术上讲它不再是一棵树)?
(抱歉我的英语不好。)
答案1
您可以name
为节点指定一个,然后使用常规 TikZ 绘图命令连接它们。您需要将 TikZ 命令括在括号中,以防止forest
括号解析器对其进行解析:
\documentclass{article}
\usepackage{forest}
\begin{document}
\begin{forest}
for tree={circle,draw,s sep=0.8cm}
[$\lambda$
[,{edge label={node[midway,left] {B}}},{text=white,fill=black}
[,{edge label={node[midway,left] {A}}}
[,{edge label={node[midway,left] {B}}}
[,name=A2,{edge label={node[midway,left] {A}}},
{text=white,fill=black}]
]
]
]
[,name=A1,{edge label={node[midway,right] {A}}}
[,{edge label={node[midway,right] {B}}},
{text=white,fill=black}
[,{edge label={node[midway,right] {A}}},
{text=white,fill=black}]
]{\draw[->] (A2) .. controls +(right:1) and +(left:1) .. (A1);}
]
]
\end{forest}
\end{document}
答案2
以下是Alan Munn 的回答如果您不喜欢打字或者需要以这种风格画很多树,这可能会引起您的兴趣。
我定义了树的样式labelled tree
并circle tree
用于树的序言中。
labelled tree
激活一种允许你指定
<content>:<edge label>
作为节点的内容,并让边标签自动定位到左侧或右侧。
circle tree
只是使节点变成圆圈等等。
此外,inverse
将文本设置为白色,并将填充设置为黑色。
最后,arrow to
是一种采用三个参数的样式。
arrow to={<first control point>}{<second control point>}{<node to connect to>}
这允许您将连接器指定为应从中绘制连接的节点的选项。可以使用相对节点名称(例如!r2
在此示例中)或使用指定的标签name
(如 Alan 的答案中所示)来指定要连接的节点。
这意味着我们可以使用以下代码绘制艾伦的树。
\begin{forest}
labelled tree,
circle tree,
[$\lambda$
[:B, inverse
[:A
[:B
[:A, inverse, arrow to={right:1}{left:1}{!r2}
]
]
]
]
[:A
[:B, inverse
[:A, inverse
]
]
]
]
\end{forest}
更普遍,
\begin{forest}
labelled tree,
circle tree,
[$\lambda$
[:B, inverse
[:A
[:B
[:A, inverse, arrow to={right:1}{left:1}{!r2}
]
]
]
]
[:A
[:B, inverse
[:A, inverse
]
]
]
]
\end{forest}
\begin{forest}
labelled tree,
circle tree,
[$\lambda$
[:B, inverse
[:A
[:B
[:A, inverse, arrow to={left:1}{left:1}{!r1}
]
]
]
]
]
\end{forest}
\begin{forest}
labelled tree,
circle tree,
[$\lambda$
[:B, inverse
[:A
[:B
[:A, inverse, arrow to={right:1}{left:1}{!r2}
]
]
]
]
[:A
[:B, inverse
[:A, inverse
]
]
]
[:B
[:A, inverse
[:B
[:A, inverse, arrow to={left:1}{right:1}{!r2}
]
]
]
]
]
\end{forest}
\begin{forest}
labelled tree,
circle tree,
[$\lambda$
[$\omega$
[:B, inverse
[:A
[:B
[:A
[:B, inverse, arrow to={right:1}{left:1}{!uuu2}
]
]
]
[:A
[:B
[:A, inverse, arrow to={right:1}{left:1}{!r12}
]
]
]
]
]
[:A
[:B, inverse
[:A, inverse
]
]
]
[:B
[:A, inverse
[:B
[:A, inverse, arrow to={left:1}{right:1}{!r12}
]
]
]
]
]
]
\end{forest}
生产
完整代码:
\documentclass[border=10pt]{standalone}
\usepackage{forest}
\forestset{
declare boolean register=sloped labels,
not sloped labels,
my edge label/.style={
tempcountc/.option=grow,
if reversed={
tempcountc-/.register=tempcountb,
}{
tempcountc+/.register=tempcountb,
},
if sloped labels={
temptoksa=sloped,
}{
temptoksa=,
},
edge label/.expanded={node [midway, shift=(\foresteregister{tempcountc}:10pt), \foresteregister{temptoksa}] {#1}}
},
labelled tree/.style={
before typesetting nodes={
where={(n_children())>1}{
tempcounta/.pgfmath={int(((n_children())+1)/2)},
if={isodd(n_children())}{
for n/.wrap pgfmath arg={{##1}{calign with current}}{(tempcounta)},
}{},
for nodewalk={
n=1,
filter={current and siblings}{n()<(tempcounta)},
}{
for nodewalk={
c,
while={int(n_children())==1}{
on invalid={fake}{n=1},
}{},
}{
tempcountb'=-90,
split option={content}{:}{content,my edge label},
},
},
for nodewalk={
n'=1,
filter={current and siblings}{n()>=(tempcounta)},
}{
for nodewalk={
c,
while={int(n_children())==1}{
on invalid={fake}{n=1},
}{},
}{
tempcountb'=-270,
split option={content}{:}{content,my edge label},
},
},
}{},
for nodewalk={
fake=r,
while={int(n_children())==1}{
on invalid={fake}{n=1},
}{},
}{
tempcountb'=-270,
split option={content}{:}{content,my edge label},
},
},
},
arrow to/.style n args=3{
tikz+={
\draw [->] () .. controls +(#1) and +(#2) .. (#3);
}
},
inverse/.style={text=white, fill=black},
circle tree/.style={
for tree={
circle,
draw,
s sep=0.8cm,
edge={->},
},
}
}
\begin{document}
\begin{forest}
labelled tree,
circle tree,
[$\lambda$
[:B, inverse
[:A
[:B
[:A, inverse, arrow to={right:1}{left:1}{!r2}
]
]
]
]
[:A
[:B, inverse
[:A, inverse
]
]
]
]
\end{forest}
\begin{forest}
labelled tree,
circle tree,
[$\lambda$
[:B, inverse
[:A
[:B
[:A, inverse, arrow to={left:1}{left:1}{!r1}
]
]
]
]
]
\end{forest}
\begin{forest}
labelled tree,
circle tree,
[$\lambda$
[:B, inverse
[:A
[:B
[:A, inverse, arrow to={right:1}{left:1}{!r2}
]
]
]
]
[:A
[:B, inverse
[:A, inverse
]
]
]
[:B
[:A, inverse
[:B
[:A, inverse, arrow to={left:1}{right:1}{!r2}
]
]
]
]
]
\end{forest}
\begin{forest}
labelled tree,
circle tree,
[$\lambda$
[$\omega$
[:B, inverse
[:A
[:B
[:A
[:B, inverse, arrow to={right:1}{left:1}{!uuu2}
]
]
]
[:A
[:B
[:A, inverse, arrow to={right:1}{left:1}{!r12}
]
]
]
]
]
[:A
[:B, inverse
[:A, inverse
]
]
]
[:B
[:A, inverse
[:B
[:A, inverse, arrow to={left:1}{right:1}{!r12}
]
]
]
]
]
]
\end{forest}
\end{document}