如何让所有森林节点从左到右排列且不重叠?

如何让所有森林节点从左到右排列且不重叠?

我想让所有节点从左到右按升序排列。如果我使用fit=band2 个子树,左右顺序良好,没有任何重叠。但左子树太靠右了,节点 9、11、12 从节点 13 开始就在右边。我不想为这棵树找一个特殊的解决方案,而想为树找一个共同的解决方案。

\documentclass{standalone}

\usepackage{forest}
\makeatletter\tikzset{use path/.code={\tikz@addmode{\pgfsyssoftpath@setcurrentpath#1} \appto\tikz@preactions{\let\tikz@actions@path#1}}}\makeatother
\forestset{show boundary/.style={
before drawing tree={get min s tree boundary=\minboundary, get max s tree boundary=\maxboundary}, tikz+={\draw[red,use path=\minboundary]; \draw[red,use path=\maxboundary];}}}
\begin{document}
\begin{forest} 
    for tree={l sep=1em, s sep=0.6em, anchor=center, 
        inner sep=0.3em, fill=red!50,fit=band,
        circle,minimum size=20pt, font=\sffamily
    },
  [13
    [4,show boundary
        [2]
        [5
                [,phantom]
            [7
                [,phantom]
                [9
                    [,phantom]
                    [11
                        [,phantom]
                        [12]
                    ]
                ]
            ]
        ]
    ]
    [19]
  ]
\end{forest}
\end{document}

[不按顺序1

答案1

13 的幻像子元素位于 4 到 19 之间,并且fit=band与父元素 13 ( calign with current) 垂直对齐,这样就可以达到目的。

\documentclass{standalone}

\usepackage{forest}
\makeatletter\tikzset{use path/.code={\tikz@addmode{\pgfsyssoftpath@setcurrentpath#1} \appto\tikz@preactions{\let\tikz@actions@path#1}}}\makeatother
\forestset{show boundary/.style={
before drawing tree={get min s tree boundary=\minboundary, get max s tree boundary=\maxboundary}, tikz+={\draw[red,use path=\minboundary]; \draw[red,use path=\maxboundary];}}}
\begin{document}
\begin{forest} 
    for tree={l sep=1em, s sep=0.6em, anchor=center, 
        inner sep=0.3em, fill=red!50,fit=band,
        circle,minimum size=20pt, font=\sffamily
    },
  [13
    [4,show boundary
        [2]
        [5
                [,phantom]
            [7
                [,phantom]
                [9
                    [,phantom]
                    [11
                        [,phantom]
                        [12]
                    ]
                ]
            ]
        ]
      ]
    [,phantom,calign with current]
    [19]
  ]
\end{forest}
\end{document}

在此处输入图片描述

编辑:为了更容易输入。可以自动幻化空节点,如下所示。请注意,(i)where content={}{phantom}{}发生在 内delay,因为在处理树前导时内容选项未“填充”;并且 (ii)where content发生在外部 for tree以避免双重循环。

\documentclass{standalone}

\usepackage{forest}
\makeatletter\tikzset{use path/.code={\tikz@addmode{\pgfsyssoftpath@setcurrentpath#1} \appto\tikz@preactions{\let\tikz@actions@path#1}}}\makeatother
\forestset{show boundary/.style={
before drawing tree={get min s tree boundary=\minboundary, get max s tree boundary=\maxboundary}, tikz+={\draw[red,use path=\minboundary]; \draw[red,use path=\maxboundary];}}}
\begin{document}
\begin{forest} 
  for tree={l sep=1em, s sep=0.6em, anchor=center, 
    inner sep=0.3em, fill=red!50,fit=band,
    circle,minimum size=20pt, font=\sffamily
  },
  delay={where content={}{phantom}{}},
  [13
    [4,show boundary
      [2]
      [5
        []
        [7
          []
          [9
            []
            [11
              []
              [12]
            ]
          ]
        ]
      ]
    ]
    [,calign with current]
    [19]
  ]
\end{forest}
\end{document}

编辑2:一个通用的自动解决方案。 这个想法是自动fit=band,calign with current在每对兄弟节点之间插入一个节点。这些节点将充当两个兄弟子树之间的“分隔符”。其他节点则不是需要fit=band。(与以前的解决方案相比,这可以正确处理一元分支内的二元分支;请参见下面的节点“X”。从代码中删除“X”即可到达原始树。)

事实上,这就是我们解决线性化问题所需要做的一切,所有其他选项都是为了更漂亮的输入;特别coordinate,phantom是使所有空节点变小且不可见。我还将代码放在样式中,以便于在多棵树中使用。

\documentclass{standalone}
\usepackage{forest}
\forestset{
  bst/.style={
    delay={
      where content={}{
        coordinate,phantom
      }{
        s sep=0.6em, anchor=center, 
        inner sep=0.3em, fill=red!50,
        circle, minimum size=20pt, font=\sffamily,
      },
      where n children=2{
        for 1={insert after={[,coordinate,phantom,calign with current,fit=band]}}
      }{},
    }
  }
}

\begin{document}
\begin{forest} bst
  [13
    [4
      [2]
      [5
        []
        [7
          [X]
          [9
            []
            [11
              []
              [12]
            ]
          ]
        ]
      ]
    ]
    [19]
  ]
\end{forest}
\end{document}

在此处输入图片描述

编辑 3:使其适用于非二叉分支树。严格来说,这比 OP 想要的要多,但对某些人来说可能有用。这个想法很简单,就是在每对相邻的兄弟节点之间放置分隔节点。这是通过 实现的where n children=0{}{for 1={for following siblings={insert before={...}}}

\documentclass{standalone}
\usepackage{forest}
\forestset{
  bst/.style={
    delay={
      where content={}{
        coordinate,phantom
      }{
        s sep=0.6em, anchor=center, 
        inner sep=0.3em, fill=red!50,
        circle, minimum size=20pt, font=\sffamily,
      },
      where n children=0{}{for 1={for following siblings={
            insert before={[,coordinate,phantom,calign with current,fit=band]},
      }}},
    }
  }
}

\begin{document}
\begin{forest} bst
  [13
    [4
      [2]
      [5
        []
        [7
          [X]
          [Y
            [1]
            [2]
          ]
          [9
            []
            [11
              []
              [12]
            ]
          ]
          [Z
            [4]
            [5
              [8]
              [9]
            ]
            [6]
          ]
        ]
      ]
    ]
    [19]
  ]
\end{forest}
\end{document}

在此处输入图片描述

答案2

该解决方案可能不是你喜欢的——我已经删除了幻影中间节点并将它们添加到最后

在此处输入图片描述

\documentclass{standalone}

\usepackage{forest}

\begin{document}
\begin{forest} 
    for tree={
         fill=red!50,fit=band,
        circle, font=\sffamily
    },
  [13
    [4
        [2]
        [5
            [7
                [9
                    [11
                        [12]
                    ]
                ]
            ]
        ]
    ]                        [,phantom]
    [19]                        [,phantom]
  ]
\end{forest}
\end{document}

相关内容