考虑下面的树。有没有一种简单的方法来标记每个左边缘 q、每个右边缘 p、每个左节点 f 和每个右节点 r,而无需手动对每个级别进行标记?
第二个问题:有没有一个好的方法可以将这个伯努利过程树示例推广到 n 级?
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{trees}
\begin{document}
\pagestyle{empty}
\tikzstyle{level 1}=[level distance=3.5cm, sibling distance=6cm]
\tikzstyle{level 2}=[level distance=3.5cm, sibling distance=3cm]
\tikzstyle{level 3}=[level distance=3.5cm, sibling distance=2cm]
\tikzstyle{bag} = [text centered,circle,draw,inner sep=0.3em]
\tikzstyle{head} = [inner sep=0pt]
\begin{tikzpicture} %
\node[head] {} %
child { %
node[bag] {} %
child{ %
node[bag]{}
child { %
node[bag, label=below: %
{$a$}] {} %
} %
child { %
node[bag, label=below: %
{$b$}] {} %
} %
}%
child{ %
node[bag]{}
child { %
node[bag, label=below: %
{$c$}] {} %
} %
child { %
node[bag, label=below: %
{$d$}] {} %
} %
}%
}
child { %
node[bag] {} %
child{ %
node[bag]{}
child { %
node[bag, label=below: %
{$e$}] {} %
} %
child { %
node[bag, label=below: %
{$f$}] {} %
} %
}%
child{ %
node[bag]{}
child { %
node[bag, label=below: %
{$g$}] {} %
} %
child { %
node[bag, label=below: %
{$h$}] {} %
} %
}%
}; % %
\end{tikzpicture}
\end{document}
答案1
我正在研究类似的东西,但我需要研究这个代码(实际上没有时间)您可以查看\pgfqkeys{/berntree}
以查看所有选项。限制是 5,但使用循环方法来构建这棵树会很好!我做了一些修改,现在您可以修改样式:node success style
一个node miss style
。要在每个分支的末尾添加一些标签,您可以使用最后的节点(这不是很容易),对于边缘上的标签,您可以使用edge style
。代码不是很好,因为箭头在某些节点内,最好为每个节点提供相同的大小。版本 4:edge style/.style = {->,>=latex',shorten <= 6pt}
针对边缘的问题,查看标签的最终循环。我修复了大小的节点
\documentclass{scrartcl}
\usepackage{pgf,tikz}
\usetikzlibrary{trees,arrows,calc}
\makeatletter
\newcount\tkz@Berndepth
\newdimen\tkz@BernLEN
\tkz@BernLEN=24em
\def\tkzBernTreeSet#{\pgfqkeys{/berntree}}
\pgfqkeys{/berntree}{%
success/.code = \def\tkz@bern@success{#1},
miss/.code = \def\tkz@bern@miss{#1},
p/.code = \def\tkz@bern@pbsuccess{#1},
q/.code = \def\tkz@bern@pbmiss{#1},
node success style/.style = {inner sep=2pt,outer sep=3pt},
node miss style/.style = {inner sep=2pt,outer sep=3pt},
edge style/.style = {->,>=latex',shorten <= 6pt},
root style/.style = {draw,circle},
success/.initial = S,
miss/.initial = E,
p/.initial = $p$,
q/.initial = $1-p$,
gap/.code = \def\tkz@bern@gap{#1},
length/.code = \def\tkz@bern@length{#1}
}
\def\tkz@brntree#1#2{%
\node[/berntree/root style] {};
\global\advance\tkz@Berndepth 1\relax
\begin{scope}[level distance=\tkz@bern@length,
level 1/.style={sibling distance=#2}]
\node[] (root) at (#1) {}
[grow=right]
child[/berntree/edge style] {%
node[/berntree/node miss style](tkz@E\the\tkz@Berndepth) {\tkz@bern@miss}
edge from parent node[fill=white] {\tkz@bern@pbmiss}}
child [/berntree/edge style] {%
node[/berntree/node success style] (tkz@S\the\tkz@Berndepth) {\tkz@bern@success}
edge from parent node[fill=white] {\tkz@bern@pbsuccess}
};
\end{scope}}%
\def\tkzBernTree{\pgfutil@ifnextchar[{\tkz@BernTree}{\tkz@BernTree[]}}
\def\tkz@BernTree[#1]#2{%
\begingroup
\pgfqkeys{/berntree}{%
success = S,
miss= E,
node success style/.style = {inner sep=2pt,outer sep=3pt,draw,minimum width=1.5em,minimum height=1.5em},
node miss style/.style = {inner sep=2pt,outer sep=3pt,circle,draw,minimum width=1.5em},
p=$p$,
q=$q$,
gap=8cm,
length=3cm}
\pgfqkeys{/berntree}{#1}
\tkz@BernLEN=\tkz@bern@gap\relax
\tkz@Berndepth 0\relax
\node (tkz@S0) at (0,0){};
\def\tkz@bn@level{#2}
\ifcase\tkz@bn@level%
\or%
\tkz@brntree{tkz@S0}{\tkz@BernLEN}
\or%
\tkz@brntree{tkz@S0}{\tkz@BernLEN}
\divide \tkz@BernLEN by 2 %
\foreach \nd in {1}{
\tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
\tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}
\or%
\tkz@brntree{tkz@S0}{\tkz@BernLEN}
\divide \tkz@BernLEN by 2 %
\foreach \nd in {1}{
\tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
\tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}
\divide \tkz@BernLEN by 2 %
\foreach \nd in {2,3}{
\tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
\tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}
\or%
\tkz@brntree{tkz@S0}{\tkz@BernLEN}
\divide \tkz@BernLEN by 2 %
\foreach \nd in {1}{
\tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
\tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}
\divide \tkz@BernLEN by 2 %
\foreach \nd in {2,3}{
\tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
\tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}
\divide \tkz@BernLEN by 2 %
\foreach \nd in {4,5,6,7}{
\tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
\tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}
\or%
\tkz@brntree{tkz@S0}{\tkz@BernLEN}
\divide \tkz@BernLEN by 2 %
\foreach \nd in {1}{
\tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
\tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}
\divide \tkz@BernLEN by 2 %
\foreach \nd in {2,3}{
\tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
\tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}
\divide \tkz@BernLEN by 2 %
\foreach \nd in {4,...,7}{
\tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
\tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}
\divide \tkz@BernLEN by 2 %
\foreach \nd in {8,...,15}{
\tkz@brntree{tkz@S\nd}{\tkz@BernLEN}
\tkz@brntree{tkz@E\nd}{\tkz@BernLEN}}
\fi
\endgroup
}
\makeatother
\begin{document}
\begin{tikzpicture}[yscale=1.2]
\tkzBernTree[root style/.style = {fill,circle,outer sep =1pt,inner sep=2pt}]{4}
\makeatletter
\foreach \num/\lab in {8/a,9/c,10/e,11/g,12/i,13/k,14/m,15/o}{%
\node at ($(tkz@S\num)+(2,0)$){$\lab$};
}
\foreach \num/\lab in {8/b,9/d,10/f,11/h,12/j,13/l,14/n,15/p}{%
\node at ($(tkz@E\num)+(2,0)$){$\lab$};
}
\makeatother
\end{tikzpicture}
\end{document}
答案2
与往常一样,对于来说,这是一项相对容易的任务forest
。
代码
\documentclass[tikz]{standalone}
\usepackage{forest}
\tikzset{
root node/.style={shape=circle, fill, draw, inner sep=+0pt, minimum size=+7pt},
el style/.style={pos=.4, inner sep=+.5pt, font=\scriptsize, fill=white},
lr style/.style={inner sep=+1pt, minimum size=+1.2em, draw}}
\newcounter{myCounter}
\forestset{
left node/.style ={content=E,
edge label={node[el style]{$p$}},
node options={shape=circle, lr style}},
right node/.style={content=S,
edge label={node[el style]{$q$}},
node options={shape=rectangle, lr style}},
bernoulli/.style={edge=-latex,
if={level()<#1}{
append={[,bernoulli={#1}, left node]}, append={[,bernoulli={#1}, right node]}
}{
/utils/exec=\stepcounter{myCounter},
append/.expanded={[$\salph{myCounter}$, edge={draw=none}]}}}}
\newcommand*\salph[1]{%
\ifnum\csname c@#1\endcsname>26 \the\csname c@#1\endcsname\else\alph{#1}\fi}
\begin{document}
\begin{forest}
[,bernoulli={5}, root node]
\end{forest}
\end{document}
输出
答案3
如果您愿意在代码中区分所使用的样式(bagr/bagl),以下是我的看法(纯文本)。我还添加了一些\strut
s 以使底部标签对齐。最重要的是 -part edge from parent path
。起初我以为我可以\tikzchildnode
立即获得坐标,但有趣的是,它会返回到0pt
任何地方,所以我不得不使用calc
库来获取某种可比较的尺寸。
\input tikz
\usetikzlibrary{calc}
\tikzpicture[
level/.style={sibling distance=6cm/#1, level distance=3.5cm},
bag/.style={text centered, circle, draw, inner sep=0.3em},
bagl/.style={bag, label=left:$f$},
bagr/.style={bag, label=right:$r$},
head/.style={inner sep=0pt},
edge from parent path={
let \p0=(\tikzparentnode),
\p{center}=($(\tikzparentnode) !.5! (\tikzchildnode) $) in
(\tikzparentnode) -- (\tikzchildnode)
\ifdim\x0>\x{center}
node [pos=.5,left] {$q$}
\else
node [pos=.5,right] {$p$}
\fi
}
]
\node[head] {}
child {
node[bagl] {}
child{
node[bagl]{}
child {
node[bag, label=below:
{$\mathstrut a$}] {}
}
child {
node[bag, label=below:
{$\mathstrut b$}] {}
}
}
child{
node[bagr]{}
child {
node[bag, label=below:
{$\mathstrut c$}] {}
}
child {
node[bag, label=below:
{$\mathstrut d$}] {}
}
}
}
child {
node[bagr] {}
child{
node[bagl]{}
child {
node[bag, label=below:
{$\mathstrut e$}] {}
}
child {
node[bag, label=below:
{$\mathstrut f$}] {}
}
}
child{
node[bagr]{}
child {
node[bag, label=below:
{$\mathstrut g$}] {}
}
child {
node[bag, label=below:
{$\mathstrut h$}] {}
}
}
};
\endtikzpicture
\bye
我怀疑有更简单的方法可以解决这一切。