如何绘制具有 90º 度分支的树形图

如何绘制具有 90º 度分支的树形图

我正在尝试在 LaTeX 中复制以下树: 在此处输入图片描述

我遇到了问题,因为 (1) 我从来没有画过像这样的具有 90º 度分支的树形图,并且 (2) 我从来没有画过带有编号示例的树形图。我尝试使用tikz-qtreeforest,但没有任何进展。所以我尝试使用tabbing环境来解决编号示例问题,但现在我不知道使用哪个包来绘制线条。这是我当前(写得很糟糕)的代码:

\documentclass[]{article}
\begin{document}
\begin{tabbing}
\hspace{0em} $(20)$ \= \hspace{2em} $n$ \= \hspace{1em} $s/(n)[n]$ \= 
\hspace{1em} $n/[s]$ \= \hspace{1em} $n$ \= \hspace{1em} $s/(n)$ \= 
\hspace{1em} $s/(n)//(s/(n))$ \= \hspace{1em} $s/(n)//(s/(n))[n]$ \= 
\hspace{1em} $n$ \= \hspace{1em} $n/(n)$\\~\\
\hspace{0em} $(21)$\= \hspace{37.5em} $n$\\~\\
\hspace{0em} $(22)$\= \hspace{17.5em} $s/(n)$\\~\\
\hspace{0em} $(23)$\= \hspace{30em} $s/(n)$\\~\\
\hspace{0em} $(24)$\= \hspace{20,5em} $s$\\~\\
\hspace{0em} $(25)$\= \hspace{14em} $n$\\~\\
\hspace{0em} $(26)$\= \hspace{6em} $s$\\
\end{tabbing}
\end{document}

导致: 在此处输入图片描述 有人能帮我解决这个噩梦吗?我必须复制第一张图片的树状图?

答案1

这是使用的版本forest

\documentclass{article}
\usepackage[edges]{forest}

\forestset{
declare count register=labelcount,
enumerate/.style={labelcount=#1,
for tree={content/.pgfmath=labelcount, labelcount-=1},
}
}

\begin{document}

\begin{forest}for tree={grow=north,forked edge,math content}
[
[s,no edge
    [n
        [s
            [s/(n)
                [n,tier=21
                    [n/(n), tier=top]
                    [n,tier=top]] 
                [{s/(n)//(s/(n))[n]},tier=top ]
                [s/(n)
                    [s/(n)//(s/(n))),tier=top ]
                    [s/(n),tier=top ]
                ]
            ]
            [n,tier=top]
         ]
        [{n/[s]},tier=top ]
    ]
    [{s/(n)[n]},tier=top ]
    [n,tier=top ]
]
[,for tree=no edge,delay={enumerate={26},for tree={content={(#1)}}}
    [[[[[,tier=21 [,tier=top ]]]]]]]
]
\end{forest}

\end{document}

代码输出

代码解释

  • 我们使用edges来自的库来forest制作简单的方形分支。
  • 我们习惯grow=north把树倒过来。
  • 使用tier密钥可以将树的所有终端节点对齐到树的顶部。它还用于将行 (21) 与 (22) 分开,因为在树中它们处于同一嵌入级别,但在编号上则不是。通过将树中的节点与编号中的节点对齐,我们可以实现所需的结果。
  • 编号是通过本质上控制树和数字的幻影根节点来完成的。
  • 这些数字是半自动计算的,通过使用密钥给出根节点的数字enumerate=...并从那里倒数。同样,tier密钥用于保持对齐正确。

答案2

\documentclass[border = 5pt]{standalone}

\usepackage{tikz-qtree}

\begin{document}
\begin{tikzpicture}[grow' = up]
  \tikzset{
    edge from parent/.style = {draw,
      edge from parent path={(\tikzparentnode.north)
        -| (\tikzchildnode)}},
    frontier/.style = {distance from root = 180pt},
  }

  % tree
  \Tree [.s [n ]
            [s/(n)[n] ]
            [.n [n/[s] ]
                [.s [n ]
                    [.s/(n) [.s/(n) [s/(n) ] 
                                    [s/(n)//(s/(n)) ] ]
                            [s/(n)//(s/(n))[n] ]
                            [ [.n [.n ]
                                [.n/(n) ] ] ] ] ] ] ]

  % labels
  \foreach \y/\lbl in {0/26,30/25,60/24,90/23,120/22,150/21,180/20} {
    \node[xshift = -3cm, yshift = \y pt] at (0, 0){\small(\lbl)}; 
  }

\end{tikzpicture}

\end{document}

在此处输入图片描述

答案3

这是改编自Alan Munn 的回答它的用途更加方便用户使用。要生成树,只需添加

enumerated,
enum'=<start line number>

其中<start line number>是第一行的编号。样式enumerated将尝试确定需要多少行,格式化树并对行进行编号。无需明确添加幻像根或节点来获取编号:这些节点都将自动添加。

唯一需要您提供帮助的情况是需要额外线路的情况,因为处于同一结构级别的两个节点应该放在不同的线路上。

结果是

\begin{forest}
  enumerated,
  enum'=20,
  [S
      [n
          [s
              [s/(n)
                  [n,tier=21
                      [n/(n)]
                      [n]] 
                  [{s/(n)//(s/(n))[n]} ]
                  [s/(n),tier=22
                      [s/(n)//(s/(n))) ]
                      [s/(n) ]
                  ]
              ]
              [n]
          ]
          [{n/[s]} ]
      ]
      [{s/(n)[n]} ]
      [n ]
  ]
\end{forest}

生产

<code>enumerated</code> 森林风格

代码:

\documentclass[border=10pt]{standalone}
\usepackage[edges]{forest}

\forestset{% addaswyd o gôd Alan Munn: https://tex.stackexchange.com/a/433753/
  declare count register=enum,
  enum'=100,
  declare toks register=enum tiers,
  enum tiers=,
  declare boolean register=enum toggle,
  not enum toggle,
  enumerated/.style={
    enum tiers=enum@tier@\foresteregister{enum},
    for tree={
      math content,
      grow=90,
    },
    forked edges,
    delay={
      tempcountc/.max={level}{tree},
      tempcountc'+=1,
      tempcountb/.register=enum,
      while={
        >R_> {tempcountc}{0}
      }{
        tempcountc'-=1,
        not enum toggle,
        where={
          > O R = {level} {tempcountc}
        }{
          if n children=0{
            tier/.process={Rw{enum}{enum@tier@##1}}
          }{
            if tier={}{
              tier/.process={Rw{tempcountb}{enum@tier@##1}},
              if={>R! RR=! & {enum toggle} {tempcountb}{enum} }{ +enum tiers/.process={Rw{tempcountb}{enum@tier@##1,}}, enum toggle } {}
            }{
              +enum tiers/.process={Ow{tier}{##1,}}
            }
          },
        }{},        
        tempcountb'+=1,
      },
    },
    before typesetting nodes={
      replace by={[, phantom, for tree={grow=90}, append, temptoksa/.option=name, split register={enum tiers}{,}{enum label}
        ]%
      },
    },
    before packing={
      delay={
        tempcounta/.register=enum,
        for nodewalk={reverse={fake=r,while nodewalk valid={l}{l}}}{content/.process={Rw{tempcounta}{(##1)}}, typeset node, tempcounta'+=1},
      }
    }
  },
  enum label/.style={
    prepend={[, grow=90, tier=#1, no edge, name=#1]},
    enum parent/.process={Rw{temptoksa}{{##1}{#1}}},
    temptoksa=#1,
  },
  enum parent/.style 2 args={
    before packing={
      for nodewalk={name=#1}{append=#2}
    },
  },
}

\begin{document}
\begin{forest}
  enumerated,
  enum'=20,
  [S
      [n
          [s
              [s/(n)
                  [n,tier=21
                      [n/(n)]
                      [n]] 
                  [{s/(n)//(s/(n))[n]} ]
                  [s/(n),tier=22
                      [s/(n)//(s/(n))) ]
                      [s/(n) ]
                  ]
              ]
              [n]
          ]
          [{n/[s]} ]
      ]
      [{s/(n)[n]} ]
      [n ]
  ]
\end{forest}
\end{document}

相关内容