我对 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 查看节点的 是否等于n
。1
对于左侧节点,我们使用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$}}},
也会做同样的事情。