深入理解平衡查找树

本次所写的平衡查找树完全是为了后面的红黑树做铺垫。

平衡二叉树已经能够更好地用于许多应用程序中,但是在最坏的情况下的性能还是很糟糕

理想情况下我们希望能够保持二分查找树的平衡性,在一棵含有N个结点的树中,我们希望树的高度为~lgN,这样我们就能保证所有查找都能在~lgN次比较内结束。

2-3查找树

为了保证查找树的平衡性,我们需要一些灵活性。

我们将一棵标准二叉树中的结点称为2-结点(含有一个键和两条链接),而现在我们需要加入3-结点,它含有两个键和三条链接。如图所示:

《深入理解平衡查找树》

一棵2-3查找树或为一棵空树,或者由以下结点组成:

  • 2-结点,含有一个键(及其对应的值)和两条链接,左链接指向的2-3树中的键都小于该结点,右链接指向的2-3树中的键都大于该结点。
  • 3-结点,含有两个键(及其对应的值)和三条链接,左链接指向的2-3树中的键都小于该结点,中键指向的2-3树种的键都位于该结点的两个键之间,右链接指向的2-3树中的键都大于该结点。

一棵完美平衡的2-3查找树中的所有空链接到根结点的距离都应该是相同的。

查找

参考二叉查找树,我们可以推算出2-3平衡树的查找算法。要判断一个键是否在树中,我们先将它和根结点中的键比较。如果和其中一个键相等,查找命中。否则我们就根据比较的结果找到指向相应区域的链接,并在其指向的子树中递归的继续查找。如果这是个空链接,查找未命中。

《深入理解平衡查找树》
《深入理解平衡查找树》

向2-结点中插入新键

要在2-3树中插入一个新结点,我们可以二叉查找树一样先进行一次未命中的查找,然后把新结点挂在树的底部。但这样的话树无法保持完美平衡性。我们使用2-3树的主要原因就在于它能够在插入后继续保持平衡。如果未命中的查找结束于一个2-结点:那么我们只需要把这个2-结点替换为一个3-结点,将要插入的键保持其中即可。

《深入理解平衡查找树》

向一棵只含有一个3-结点的树中插入新键

为了新键的插入,我们先临时将新键存入该结点中,使之成为一个4-结点。它很自然地扩展了以前的结点并含有3个键和4条链接。创建一个4-结点很方便。因为很容易将它转换为一棵由3个2-结点组成的2-3树,其中一个结点(根)含有中键,一个结点含有3个键中的最小者(和根结点的左链接相连),一个结点含有3个键中的最大者(和根结点是右链接相连)。插入前树的高度为0,插入后树的高度为1。

《深入理解平衡查找树》

向一个父结点为2-结点的3-结点中插入新键

这种情况下我们需要在维持树的完美平衡的前提下为新键腾出空间。我们先像刚才一样构造一个临时的4-结点并将其分解,但此时我们不会为中键创建一个新结点,而是将其中移动至原来的父结点中。

《深入理解平衡查找树》

向一个父结点为3-结点的3-结点中插入新键

我们再次和刚才一样构造一个临时的4-结点并分解它,然后将它的中键插入它的父结点中。因为父结点也是一个3-结点,因此我们需要再次做如上变换。直至遇到一个2-结点并将它替换成一个不需要继续分解的3-结点。

《深入理解平衡查找树》

分解根结点

如果从插入结点到根结点的路径上全都是3-结点,我们的根结点最终变成一个4-结点。我们需要将这个临时的4-结点分解为3个2-结点,使树高加1。

《深入理解平衡查找树》

局部变换

将一个4-结点分解成一棵2-3树可能有6中情况。算法的根本在于这些变换都是局部的:除了相关的结点和链接之外不必修改或检查树的其他部分。每次变换中,变更的链接数量不会超过一根很小的常数。

全局性质

局部变换不会影响树的全局有序性和平衡性:任意空链接到根结点的路径长度都是相等的。

    原文作者:SeYuFac
    原文地址: https://zhuanlan.zhihu.com/p/61631654
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞