📜  用子树表示 tikz 中的二叉搜索树 (1)

📅  最后修改于: 2023-12-03 14:56:23.272000             🧑  作者: Mango

用子树表示 tikz 中的二叉搜索树

介绍

TikZ 是一个很好的画图工具,用于绘制高质量的 LaTeX 图形。二叉搜索树是一种非常有用的数据结构,它可以在 $\log n$ 的时间里查找、插入和删除元素。在这篇文章中,我们将介绍如何用 TikZ 和子树表示二叉搜索树。

实现

我们将使用 tikz-qtree 宏包,所以在你的 LaTeX 文件的引言部分输入:

\usepackage{tikz-qtree}

我们将定义一个命令来为我们的二叉搜索树创建节点。

\newcommand{\tikznode}[2]{\tikz[baseline=(#1.base)]{\node(#1)[circle,draw,inner sep=1pt] {#2};}}

接下来,我们将定义一个命令来绘制二叉搜索树的子树。这个命令将取三个参数:节点名称、左子树名称和右子树名称。

\newcommand{\subtree}[3]{\begin{tikzpicture}[baseline=(#1.base)]\Tree[.\tikznode{#1}{#1} [.\tikznode{#2}{} ] [.\tikznode{#3}{} ] ];\end{tikzpicture}}

现在,我们可以创建一个简单的二叉搜索树。

\subtree{8}{3}{10} 

这将创建一个根节点值为 8,左子树值为 3,右子树值为 10 的二叉搜索树。

Binary Search Tree

插入节点

要向二叉搜索树中插入节点,我们可以将其插入到正确的位置。插入节点时,我们从根节点开始遍历二叉搜索树。如果节点比当前节点的值小,我们移动到左子树。如果节点比当前节点的值大,我们移动到右子树。我们重复这个过程,直到到达一个空节点。在这个点上,我们插入新的节点。

下面是插入节点到二叉搜索树的函数。

\def\insert#1#2{
  \ifx#1\subtree
    \ifnum#2<#1{[2]}{\expandafter\insert\expandafter{\csname l@\number#1\endcsname}{#2}}%
  \else
    \subtree{#2}{}{}
  \fi
}

对于这个函数,我们传入两个参数:子树名称和要插入的节点值。如果子树为空,则我们创建一个新的子树作为根节点。如果子树不为空,则我们比较节点的值和当前节点的值。如果节点的值小于当前节点的值,则我们继续在左子树中插入节点。如果节点的值大于当前节点的值,则我们继续在右子树中插入节点。

下面是一个例子,演示如何将 7 插入先前创建的二叉搜索树中。

\insert\subtree{8}{7}

这将创建一个子树,其根节点值为 7,插入到之前的二叉搜索树中。

Insertion

删除节点

要从二叉搜索树中删除节点,我们可以按以下步骤操作:

  1. 如果要删除的节点是叶子节点,则我们可以直接将其删除。

  2. 如果要删除的节点具有一个子节点,则我们可以用子节点替换该节点。

  3. 如果要删除的节点具有两个子节点,则我们需要找到其中序后继节点,然后用该节点替换要删除的节点。

下面是从二叉搜索树中删除节点的函数。

\def\delete#1#2{
  \ifx#1\subtree
    \expandafter\deletestart\expandafter{\number#1}{#2}%
  \fi
}
\long\def\deletestart#1#2#3#4#5{
  \ifnum#2<#1
    \def\left{\number#1}%
    \expandafter\deletestart\expandafter{\csname l@\number#1\endcsname}{#2}{#3}{#4}{#5}%
  \else
    \ifnum#2>#1
      \def\right{\number#1}%
      \expandafter\deletestart\expandafter{\csname r@\number#1\endcsname}{#2}{#3}{#4}{#5}%
    \else
      \if#3{}
        \if#4{}% 0 children
          \def\replace{}%
          \expandafter\replacestart\left\right%
        \else% 1 child
          \def\replace{#4}%
          \expandafter\replacestart\left\right#4%
        \fi%
      \else% 2 children
        \def\successor{#5}%
        \expandafter\successorstart#5\left\right%
        \csgundef{l@\number\successor}%
        \expandafter\replacestart\left\right{\successor}%
        \csgdef{l@\number\successor}{\csname l@\number#5\endcsname}%
        \csgdef{r@\number\successor}{\csname r@\number#5\endcsname}%
      \fi%
    \fi%
  \fi
}
\long\def\replacestart#1#2#3{\ifx#2{}\csgundef{r@\number#1}\else\ifnum#2<#1\expandafter\replacestart\expandafter{\csname l@\number#1\endcsname}{#2}{#3}\else\expandafter\replacestart\expandafter{\csname r@\number#1\endcsname}{#2}{#3}\fi\fi}
\long\def\successorstart#1#2#3#4{\ifx#2{}\def\successor{#1}\else\expandafter\successorstart\expandafter{#2}{#3}{#4}{#1}\fi}

对于这个函数,我们传入两个参数:子树名称和要删除的节点值。我们首先检查此节点是否是根节点,然后根据插入节点的方法进行遍历。如果节点的值小于当前节点的值,则我们继续在左子树中删除节点。如果节点的值大于当前节点的值,则我们继续在右子树中删除节点。如果我们找到要删除的节点,则我们执行上述步骤。

删除节点的同时,我们也需要更新其子树中的所有节点的名称。为此,我们将使用类似于插入节点时使用的 \left\right 变量,以便在遍历树时方便地跟踪左右子树。

下面是一个例子,演示如何从上面插入节点的二叉搜索树中删除节点 3。

\delete\subtree{8}{3} 

这将删除节点 3 并重建二叉搜索树。

Deletion

结论

在本文中,我们介绍了如何用 TikZ 和子树表示二叉搜索树。我们还展示了如何插入和删除节点。我们希望这篇文章对你有所帮助,如果你有任何问题或评论,请留言。