首页 > 其他分享 >红黑树

红黑树

时间:2023-06-25 09:57:20浏览次数:24  
标签:结点 插入 查找 link key 红黑树

简介

红黑树是平衡二叉查找树的一种,前面我们提到,非平衡的 BST,在只有随机插入和查询的情况下,时间复杂度是 $O(\log n)$ 的,然而,如果同时存在随机插入和随机删除,那么时间复杂度会退化到 $O(\sqrt n)$,这是我们无法接受的。

红黑树在插入和删除时,会维持树的平衡,即保证树的高度在 $[\log n, \log(n + 1)]$,理论上极端情况可能树高最大会到达 $2 * \log n$,实际上很难遇到(尽管这样,还是保证了 $O(\log n)$ 的增删查改时间复杂度。

红黑树其实是 2-3 查找树或者 2-3-4 查找树的一种二叉树的实现方式。其中基于 2-3 树实现的红黑树被称为左倾红黑树(Left-Leaning Red-Black Trees, LLRB),基于 2-3-4 树实现的就是普通的红黑树,左倾红黑树实现起来比红黑树更简单一些(《算法 第四版》里面也主要讲的左倾红黑树),因此先讲左倾红黑树。

2-3 查找树

在普通的二叉树中,非叶子结点可以有一个或者两个子结点,如果没有子结点,那么就是叶子结点。

而 2-3 查找树的限制要严格很多。我们将拥有一个 key 和两个链接 的结点称为 2- 结点,拥有两个 key 和三个链接的结点称为 3- 结点。

  • 2- 结点含有一个 key,两个 link;
  • 3- 结点含有两个不同的 key,三个 link。

3- 结点含有两个 key($key_1 < key_2$),三个链接,左链接指向 2-3 树中的 key 都小于 $key_1$,中间链接指向的 2-3 树中的 key 都满足 $key_1 < key < key_2$,右链接指向的 2-3 树中的 key 都大于 $key_2$。

2-3 查找树只能由 2- 结点或者 3- 结点组成(这里不统计空结点(null)),可以看到 2-3 查找树的限制是非常严格的,这也让它可以拥有一些非常理想的性质。

一颗完美平衡的 2-3 查找树中所有空结点(null)到根结点的距离都应该是相同的,后续我们都使用 2-3 树指代一颗完美平衡的 2-3 查找树。(其他情况下表示的可能是一种更一般的结构)。

查找

将二叉查找树的查找算法一般化就能得到 2-3 树的查找算法。

向 2- 结点中插入新 key

首先进行一次未命中的查找,如果未命中的查找结束于一个 2- 结点,那么我们往这个 2- 结点中插入新的 key,使这个 2- 结点变成 3- 结点就好了,不影响所有结点的树高。

插入 key 时,由于 2-3 树的性质,我们必定是在叶子结点处执行插入。

向 3- 结点中插入新的 key

1. 向一个只含有一个 3- 结点的树中插入新 key

先组成一个临时的 4- 结点,然后将 4- 结点中的三个 key 中间的 key 上移作为剩下的 3- 结点的父结点。如下图所示:

注意到,这样操作之后,2-3 树的高度 $+1$ 了,所有原来位置的结点高度均 $+1$。

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

还是先组成一个临时的 4- 结点,然后将 4- 结点的三个 key 中中间的 key 上移,将这个 key 插入到本来为 2-结点的父结点组成 3- 结点,树的高度不变,如下图所示:

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

还是先组成一个临时的 4- 结点,然后将 4- 结点的三个 key 中中间的 key 上移,即将这个 key 插入到父结点中:此时情形就可以转化成 $1$ 或者 $2$ 或者 $3$。

如果转换成 $3$,那么就相当于是递归操作。

因此,对于 $3$ 这一插入类型,我们可以从递归的角度去理解它,递归终止条件就是切换到情形 $1$ 或者 $2$,每次递归中执行的操作就是构成一个临时的 4- 结点,然后将 4- 结点的三个 key 中中间的 key 上移,插入到父结点中。

如下图所示:

从插入操作我们可以分析得出,对 2-3 树来说,插入操作不会破坏它的完美平衡!要么整棵树的高度不变,要么整颗树的高度 $+1$,因此,根结点到所有 null 结点的长度依旧是相同的。

2-3 树的树高介于 $\log n$ 和 $\log_3 n$ 之间。

删除结点

待会再自己写,《算法 第四版》上并没有写。。。

总结

直接实现 2-3 树比较复杂,执行插入、删除操作时要维护和变换的信息比较多,可能性能还不如普通的二叉查找树。

尽管我们可以用不同的数据类型表示 2- 结点和 3- 结点并写出变换所需的代码,但用这种直白的表示方法实现大多数的操作并不方便,因为需要处理的情况实在太多。我们需要维护两种不同类型的结点,将被查找的键和结点中的每个键进行比较,将链接和其他信息从一种结点复制到另一种结点,将结点从一种数据类型转换到另一种数据类型,等等。实现这些不仅需要大量的代码,而且它们所产生的额外开销可能会使算法比标准的二叉查找树更慢。

左倾红黑树(LLRB)

红黑树的基本思想是用标准的二叉查找树(结点都是 2- 结点),以及一些额外的信息(用来替换 3- 结点)来表示 2-3 树。

我们将树中的 link 分为两类,一类是 red link 将两个 2- 结点连接起来,就构成了一个 3- 结点,合法的 LLRB 要求只有父结点和左子结点之间的 link 才能是红色的;另一类是 black link 将两个 2- 结点连接起来,对应 2-3 树中的普通 link。

准确说,我们将 3- 结点表示为由一个左斜的 red link 相连的两个 2- 结点,如所示,我们可以直接使用标准 BST 的 get 方法。

LLRB 的另一种定义是含有 red 和 black link 并且满足下列条件的二叉查找树:

  • red link 均为左斜 link;
  • 没有一个结点同时和两条 red link 相连;
  • 该树是完美黑色平衡的,即任意 null 结点到根结点的路径上的 black link 数量相同。

如果我们将一颗 LLRB 中的 red link 画平,那么所有 null 结点到根结点的距离都将是相同的。

由于每个结点都只有一个父结点,因此对每个结点来说,从它的父结点到它自身的 link 是唯一的,因此我们可以将 link 的颜色保存再表示结点的类 Node 的布尔成员变量 color 中。我们规定 null link 是黑色的

const bool kRed = true;
const bool kBlack = false;
class Node {
  private:
    int key_;
    int val_;
    int cnt_;
    bool color_;
    Node *left_;
    Node *right_;

  public:
    Node(int key, int val, int cnt, bool color) :
        key_(key), val_(val), cnt_(cnt), color_(color), left_(nullptr), right_(nullptr) {
    }

  private:
    bool isRed(Node *x) {
        if (x == nullptr) {
            return false;
        }
        return x->color_ == kRed;
    }
};

标签:结点,插入,查找,link,key,红黑树
From: https://www.cnblogs.com/zwyyy456/p/17502175.html

相关文章

  • 数据结构和算法系列课程(01)--- 排序二叉树和红黑树
    把排序二叉树放在这个系列课程的第一个部分似乎有些唐突,但是考虑到它在面试中出现的可能性,把它放在这样的一个位置也就不足为奇了。关于树和二叉树的基础知识,可以到下面的链接中下载我的课件进行了解。下面给出一个排序二叉树的Java实现:packagcom.loonstudio;/***排序二叉树......
  • C#数据结构-红黑树实现
    参考网址: https://zhuanlan.zhihu.com/p/353948322二叉查找树,他对于大多数情况下的查找和插入在效率上来说是没有问题的,但是他在最差的情况下效率比较低。红黑树保证在最坏的情况下插入和查找效率都能保证在对数的时间复杂度内完成。红黑树的性质:性质1.节点是红色或黑色性质2.根是......
  • hashmap怎么解决哈希冲突问题?红黑树和AVL树有何区别?
    链地址法hashmap是一种基于数组和链表(或红黑树)的数据结构,它可以通过hash函数将任意长度的键映射到一个固定长度的索引,从而实现快速的存取操作。但是,由于hash函数的结果是有限的,而键的数量是无限的,所以可能存在不同的键映射到同一个索引的情况,这就叫做哈希冲突。为了解决哈希冲突,has......
  • java面试 关于红黑树
    红黑树(Red-BlackTree):是一种自平衡的二叉搜索树,它在实际的软件开发中广泛应用。红黑树的特点是具有高效的插入、删除和查找操作,并且保持树的平衡,以保证这些操作的时间复杂度为O(logn)。红黑树与AVL树有什么区别?红黑树和AVL树都是自平衡的二叉搜索树,但它们在维护平衡方......
  • CS61B_红黑树转换
        ......
  • 万字长文之HashMap源码解析(包含红黑树)
    〇、储备知识之红黑树0.1>2-3树红黑树是一种自平衡的二叉树,它可以避免二分搜索树在极端的情况下蜕化成链表的情况。那么什么是红黑树呢?要想便于了解红黑树,我们先了解一下跟它息息相关的2-3树。2-3树是一种绝对平衡的多叉树,在这棵树中,任意一个节点,它的左右子树的高度是相同的。如下......
  • 红黑树是怎么来的
    平衡的关键书接前文。在前文《二叉搜索树的本质》中我们提到,二叉搜索树在实践中有个很大的问题:树倾斜。按如下顺序插入数据会让二叉搜索树退化成普通链表,进而相关操作的时间复杂度退化到O(n):怎样让这棵树在写操作后仍然保持平衡呢?R教授一边呷着黑咖啡,一边盯着这棵“畸形”......
  • 红黑树
    概要目录1红黑树的介绍2红黑树的应用3红黑树的时间复杂度和相关证明4红黑树的基本操作(一)左旋和右旋5红黑树的基本操作(二)添加6红黑树的基本操作(三)删除    作者:SkyWang  于2013-08-08                概述:R-BTree,又......
  • 手写HashMap JDK1.7(无红黑树)
    publicinterfaceMyMap<K,V>{Vget(Kk);Vput(Kk,Vv);intsize();Vremove(Kk);booleanisEmpty();}packagemain.java.com.hashmap;publicclassMyHashMap<K,V>implementsMyMap<K,V>{finalstaticint......
  • 4月24日红黑树插入实现
    继搜索二叉树和AVL树后有了红黑树。AVL树改善了搜索二叉树在极端情况下的严重效率退化,但是在运用得过程中发现他对平衡的要求几乎达到了苛刻的地步,往往经过一系列复杂的变化只是将树的深度优化了一点点,而这一点点在现在日益快速的处理器下根本不起眼,于是有了更优的结构红黑树:红......