使用森林包在树中绘制向后链接/指针

使用森林包在树中绘制向后链接/指针

我尝试了几种方法但还是无法找到可行的解决方案。

假设我使用 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}

它看起来像这样:

树 1

我想在两个不同分支的节点之间画一个向后的箭头。使用 forest 包是否可行(因为从技术上讲它不再是一棵树)?

树 2

(抱歉我的英语不好。)

答案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 treecircle 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}

相关内容