查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树

平衡2-3-4树

一棵2-3-4树是这样一棵树:它或者为空,或者是由以下三类节点组成的树:2-节点,有1个关键字和由关键字划分的2个区间链接;3-节点,有2个关键字和由关键字划分的3个区间链接;4-节点,有3个关键字和4个区间链接。
一棵平衡2-3-4树是一棵2-3-4搜索树,其中所有指向空树的链接到树根的距离都相同。

《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》

插入操作

在平衡2-3-4树中,每次进行插入仍然能在树中保持完美的平衡状态。例如,

  • 如果搜索终止处的节点是一个2-节点,就把它转变成一个3-节点。
  • 如果搜索终止处是一个3-节点,就把它转变成一个4-节点。

如果搜索终止处是一个4-节点,而且其父节点也是一个4-节点,那该怎么办呢?

解决办法是在自顶而下的过程中,如果遇到一个4-节点,就先把它分裂成两个2-节点,然后把关键字之一传递到父节点上,并改变该节点的父节点。如下图所示:

《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》

通过这种方法,就能保证自上而下处理时,当前节点的父节点不会是一个4-节点。
当然,当前节点的父节点不会是一个4-节点的递归前提,是根节点不是4-节点。如果根节点成为了4-节点,意味着树的高度要增加了。就把它变成3个2-节点组成的三角形,使树增高一层。如下图右下角所示:
《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》

性能分析

普通二叉搜索树的插入操作十分简单,但树很容易不平衡。搜索的时间开销跟树高呈正相关的关系。树越平衡,搜索越快。
2-3-4树的最大特点是维持了树的平衡,因此搜索时很快。树高在最坏情况下为lgN(所有结点都是2-node型),最好情况下为lg4 N = 1/2 lgN(所有结点都是4-node型),2-3-4树的查找、插入操作都是lgN。
然而,2-3-4树的维护、管理开销太大。

AVL树(平衡二叉树)

平衡二叉树要求对于每一个节点来说,他的左右子树的高度之差不超过1,如果插入或者删除一个结点使得高度之差大于1,就要进行节点之间的旋转(左旋或者右旋),将二叉树重新维持在一个平衡状态。
AVL树解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最坏和最好情况都维持在O(logN)。
缺点:频繁旋转会牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了许多。

节点的平衡因子是它的左子树的高度减去它的右子树的高度。带有平衡因子1、0或 -1的节点被认为是平衡的。带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。
所谓失去平衡的最小子树,是以距离插入结点最近的、且平衡因子绝对值大于1的结点作为根的子树。我们下面说的旋转,就是要旋转这个最小子树。
当AVL树不平衡时,有以下四种情况:LL、LR、RR、RL。
针对四种种情况可能导致的不平衡,可以通过旋转使之变平衡。有两种基本的旋转:
(1)左旋转:将根节点旋转到(根节点的)右孩子的左孩子位置
(2)右旋转:将根节点旋转到(根节点的)左孩子的右孩子位置
有人也把左旋转叫做逆时针旋转,右旋转叫做顺时针旋转。

节点的表示

struct Avl{  
    int v, height;  
    Avl *lchild, *rchild;
    Avl(int a):v(a),height(1),lchild(NULL),rchild(NULL){}
};

实现细节

左倾红黑树(LLRBT)

红黑树是对2-3-4树的一种二叉树实现,兼具二叉查找树维护简单和2-3-4树快速搜索的特点。
红黑树:一种二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。
下面介绍左倾红黑树(LLRBT),它比标准红黑树更简单。

  • 红链接表示内部链接,用于把要表示成3-节点和4-节点的小的二叉树链接到一起。
  • 黑链接表示外部链接,用于把2-3-4树链接到一起。

基本性质

LLRBT有以下特点:

  1. 用红链接来连接2-节点,表示3-节点和4-节点。
    《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》

  2. 3-节点必须是向左倾斜的(两者的大者作为根)。

    1. 红节点的孩子节点必须是黑节点,即不能存在两个连续的红节点。
  3. 对每个节点,从该节点到其叶子节点的所有路径上包含相同数目的黑节点。

LLRBT比标准红黑树多了特点2,标准红黑树中允许向右倾斜的红链接。

另外,LLRBT和2-3-4树是一一对应的。

《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》

红黑树的插入操作

插入算法要用到前面提过的左旋转、右旋转操作:
《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》 《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》

红黑树插入的实现思路:

  1. 和2-3-4树的插入类似,先自上而下搜索(遇到4-节点)则分裂。
  2. 若搜索失败,就在叶子节点处插入。
  3. 插入后,可能违反“红链接左倾”“两个红链接不可连续”的性质,再自下而上进行旋转调整,恢复性质。

自上而下搜索并分裂4-节点

自上而下进行搜索时,如果遇到4-节点(左右都为红链接),要先进行分裂,也就是颜色翻转,即把左右红链接变黑、父链接变红。
《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》

问题在于,对4-节点的分裂影响到了其父节点。根据父节点的不同,又分为以下两种情况:

一、父节点是2-节点
《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》

二、父节点是3-节点
《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》

注意,正如上面提到的,自上而下的分裂4-节点,保证了4-节点的父节点不可能也是4-节点。
当然,当开始搜索时,发现根节点是4-节点,为了能向下进行,需要把根节点分裂成三个2-节点的三角形,将树高度增加一层。

插入新节点并调整

当插入一个新节点时,要把它定义成红节点。待插入位置如果是2-节点、3-节点就直接插入。若插入后违反性质,则通过旋转作调整。
2-节点和3节点分别有以下几种情形:
1. 2-节点
《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》
2. 3-节点
《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》

插入操作概括

插入操作涉及到下面4个部分:插入、分裂(颜色翻转)、旋转维持左倾、旋转维持平衡。
《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》

而下面是红黑树的插入操作的具体实现:
《查找:平衡2-3-4树、AVL树(平衡二叉树)、(左倾)红黑树》

上述的递归操作的步骤是先自上而下分裂,再插入,然后自下而上调整。如果把分裂放在插入之后,即先自上而下搜索,再插入,然后自下而上分裂、调整,得到的就是2-3树。

红黑树和AVL树的比较

红黑树是牺牲了严格的高度平衡的优越条件为代价,红黑树能够以O(log2 n)的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。当然,还有一些更好的,但实现起来更复杂的数据结构能够做到一步旋转之内达到平衡,但红黑树能够给我们一个比较“便宜”的解决方案。红黑树的算法时间复杂度和AVL相同,但统计性能比AVL树更高。

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/jinzhao1993/article/details/50522966
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞