重新创建一棵树,并将节点放在一行上

重新创建一棵树,并将节点放在一行上

我对 TikZ 还很陌生,说实话,我对这个网站还不熟悉(我是在一位更有经验的朋友的帮助下写这个问题的),我正在尝试重新创建随后的照片

在此处输入图片描述

到目前为止,我通过搜索这个网站和令人生畏的 TikZ 手册整理出了以下内容

\documentclass[11pt]{book}
\usepackage{amsmath}
\usepackage{tikz}
\usepackage{tikz-qtree}
\usepackage{forest}
\usetikzlibrary{arrows.meta}
\begin{document}
    \begin{tikzpicture}[every tree node/.style={circle,draw,inner sep=1.2,fill=black},
        level distance=1.5cm,sibling distance=0.5cm, edge from parent/.append style={->,>={Latex[length=6pt,width=3pt]}},grow'=up
        ]
        \Tree[
        .\node (g) [label=below:{$g$}]{};
        [.\node (e) [label=left:{$e$}]{};
        [.\node (c) [label=left:{$c$}]{};
        [.\node (a) [label=left:{$a$}]{};]
        [.\node (b) [label=right:{$b$}]{};]
        ]
        [.\node (d) [label=right:{$d$}]{};]
        ]
        [.\node (f) [label=right:{$f$}]{};]
        ];
    \end{tikzpicture}
\end{document}

下图就是 在此处输入图片描述

我也尝试过使用森林环境

\begin{forest}
        for tree={
            circle,
            draw,
            fill=black,
            edge={<-,>={Latex[length=6pt,width=3pt]}},
            grow'=north,
            parent anchor=north,
            child anchor=south,
            calign=fixed edge angles,
            inner sep=0.5pt
        }
        [g, label=below:{$g$}
        [e, label=left:{$e$}
        [c, label=left:{$c$}
        [a, label=right:{$a$}]
        [b, label=right:{$b$}]
        ]
        [d, label=right:{$d$}]
        ]
        [f, label=right:{$f$}]
        ]
    \end{forest}

拍摄了以下照片 在此处输入图片描述

我不明白为什么节点大小不同以及如何解决这个问题。您有什么建议来重新创建边缘似乎出现在一条线上的原始图像?

答案1

请用我随后的帖子而不是下面的代码。链接的答案演示了此版本的问题,并提供了解决该问题的代码。


g由于的深度大于 ,因此您将获得不同大小的节点a,并且f的高度也大于 。如果您想象在字母周围画一个紧密贴合的圆圈,您会发现大小将取决于字母。解决此问题的一种方法是在排版节点之前删除节点的内容。由于这些与标签相同,我们不妨将内容用于标签并简化输入语法。

然后我们需要一种样式,它可以确定标签的放置位置并对其进行格式化。

我还删除了一些格式指令,这些指令实际上使您的输出不那么像目标图像,并修改了箭头规范,使它们指向正确的方向。

生成的树具有统一大小的节点和格式化的标签

\documentclass[11pt]{book}
% ateb: https://tex.stackexchange.com/a/703351/ i gwestiwn Arian: https://tex.stackexchange.com/q/703321/
\usepackage{amsmath}
\usepackage{forest}
\usetikzlibrary{arrows.meta}
\begin{document}
\begin{forest}
  for tree={
    circle,
    fill=black,
    edge={{Latex[length=6pt,width=3pt]}-},
    grow'=north,
    calign=fixed edge angles,
    inner sep=0.5pt,
  },
  before typesetting nodes={
    for tree={%
      my label/.option=content,
      content={.},
    }
  },
  my label/.style={%
    label/.process={ O+nn= ? p w1 {level}{0} {_{below}} {On= ? {n}{1} {left}{right}} {##1:{$#1$}} },
%   if level=0{label=below:{$#1$}}{if n=1{label=left:{$#1$}}{label=right:{$#1$}}},
  },
  [g 
    [e 
      [c 
        [a ]
        [b]
      ]
      [d ]
    ]
    [f ]
  ]
\end{forest}
\end{document}

请注意,复杂的

    label/.process={ O+nn= ? p w1 {level}{0} {_{below}} {On= ? {n}{1} {left}{right}} {##1:{$#1$}} },

看起来比实际要简单。至少读起来更简单。我发现包含以下内容时写起来并不简单?。从左到右阅读,O+nn= ? p w1指定后面参数的性质以及如何处理它们。{level}{0} {_{below}} {On= ? {n}{1} {left}{right}} {##1:{$#1$}}是需要处理的参数。

O说第一个参数是选项的名称,Forest 应该获取该选项的值。n说第二个参数是数字。=要求 Forest 确定第一个参数是否等于第二个参数。查看参数,这相当于询问 Forestlevel当前节点的 是0。对于根节点来说这是正确的,但对于其他节点则不然。

?有条件的。它表示如果刚刚通过的测试 Forest 应该使用下一个参数 ( _{below});否则,应该使用之后的参数 ( On= ? {n}{1} {left}{right})。因此,对于根节点,我们将得到_{below}。对于任何其他节点,我们将得到On= ? {n}{1} {left}{right}

p告诉 Forest 将参数处理应用于此参数。(这让我很困惑 - 我以为我需要一个+p,但手册中的一个例子表明不需要,并+给出了错误。)

在 的情况下root_{below}就只会导致below

对于任何其他节点,On= ? {n}{1} {left}{right}我们的结构与之前相同:获取一个选项,查看它是否等于某个数字,然后使用相关参数。在本例中,我们告诉 Forest 查看节点的 是否等于n1对于左侧节点,我们使用left,结果为 true;对于右侧节点,我们使用 ,结果为 false right

最后,w1包装我们通过所有测试获得的值并将其用作##1中的参数##1:{$#1$}。因此,对于左侧节点,根节点的标签将位于下方,而其他节点的标签将位于左侧,对于右侧节点,则位于右侧。#1是我们传递给 的参数my label,恰好是节点的内容。

如果你愿意,你可以使用嵌套的 s 来编写代码if。例如,

if level=0{label=below:{$#1$}}{if n=1{label=left:{$#1$}}{label=right:{$#1$}}},

也会做同样的事情。

相关内容