《 常见算法与数据结构》平衡查找树(2)——红黑树(附动画)

本系列文章主要介绍常用的算法和数据结构的知识,记录的是《Algorithms I/II》课程的内容,采用的是“算法(第4版)”这本红宝书作为学习教材的,语言是java。这本书的名气我不用多说吧?豆瓣评分9.4,我自己也认为是极好的学习算法的书籍。

通过这系列文章,可以加深对数据结构和基本算法的理解(个人认为比学校讲的清晰多了),并加深对java的理解。


红黑树介绍

红黑树是一种简单的实现2-3树的数据结构,它方便的把我们之前实现的二叉搜索树改造成了一棵2-3树。它的核心思想是用一条左倾链(红链)作为“胶水”把二叉树的两个节点给粘起来,形成一个3节点。

把红链看成水平的,看是不是和2-3树就一样了

BST改造成红黑树有一些约定:

  • 每个节点最多只有一个红链与之相连(连父亲和孩子)
  • 每条从root到null的路径,都是同样的黑链数(绝对黑平衡)
  • 红链都在左边

这样做的好处是什么?就是之前写的代码很多基本可以不用改就可以直接用(比如get,floor,ceiling操作,因为这些操作是不需要考虑红黑链的)

红黑树表示

红黑树表示只用在BST中加入一个用来表明链的颜色的变量就行了。默认空链是黑色,我们把颜色加在node节点的属性中,通过查找孩子的node节点颜色,我们就知道指向这个节点的链的颜色了。

 private static final boolean RED   = true;
 private static final boolean BLACK = false;
 private class Node
 {
    Key key;
    Value val;
    Node left, right;
    boolean color;
// color of parent link
 }
 private boolean isRed(Node x)
 {
    if (x == null) return false;
    return x.color == RED;
 }

红黑树操作

左旋操作

这个操作用来修正因任何情况导致红链出现在右边的情况。操作主要步骤:

  1. h的右孩子变成x的左孩子,h变成红色
  2. x的左孩子变成h,x变成黑色
  3. x作为新的子链返回

public Node rotateLeft(Node h)
{
    assert isRed(h.right);
    Node x = h.right;
    h.right = x.left;   //step 1
    x.left = h;        //step 2
    x.color = h.color;
    h.color = RED;
    return x;     //setp 3
}

右旋操作

和左旋操作差不多,只是方向变了

  1. h的左孩子变成x的右孩子,h变成红色
  2. x的右孩子变成h,x变成黑色
  3. x作为新的子链返回
public Node rotateRight(Node h)
{
    assert isRed(h.left);
    Node x = h.left;
    h.left = x.right;   //step 1
    x.right = h;        //step 2
    x.color = h.color;
    h.color = RED;
    return x;     //setp 3
}

颜色翻转

操作实现也比较简单,因为4节点的实现还是用的二叉树,我们只用把链的颜色改变就行了。

private void flipColors(Node h)
{
    assert !isRed(h);
    assert isRed(h.left);
    assert isRed(h.right);
    h.color = RED;
    h.left.color = h.right.color = BLACK;
}

插入操作

插入只有1个节点的树

  • 如果是插入左边,那么比较简单,直接是插入操作加上把节点改成红色就行了
  • 如果是插入右边,那么需要做一个左旋操作。

插入底部的一个2-节点

  • 和第一种情况一样

插入只有2个节点的树

  1. 如果比它们都大,则插入最右边,形成4-节点,进行颜色翻转, 就行了
  2. 如果比它们都小,则插入最左边,这时候中间节点有2条红链,进行右旋操作, 和1就一样了
  3. 如果在它们之间,则插入左边节点的右侧,这时候,要进行左旋,就和2一样了。

插入底部的一个3-节点

  • 和上面一样,颜色翻转后,在逐层往上检查是不是有需要调整的地方(旋转,颜色翻转)

插入总结

其实所有的插入操作,可以归结为下面三种:

  1. 右红,左黑:左旋
  2. 左红,左孩左红:右旋
  3. 双孩子红:颜色翻转

插入代码

 private Node put(Node h, Key key, Value val)
 {
        /******原插入代码*******/
        if (h == null)
            return new Node(key, val, RED);
        int cmp = key.compareTo(h.key);
        if (cmp < 0) {
            h.left = put(h.left, key, val);
        } else if (cmp > 0) {
            h.right = put(h.right, key, val);
        } else if (cmp == 0) {
            h.val = val;
        }
        h.count = 1 + size(h.left) + size(h.right);
        /******情形1*******/
        if (isRed(h.right) && !isRed(h.left))
            h = rotateLeft(h);
        /******情形2*******/
        if (isRed(h.left) && isRed(h.left.left))
            h = rotateRight(h);
        /******情形3*******/
        if (isRed(h.left) && isRed(h.right))
            flipColors(h);
        return h;
   }

红黑树构造动画

讲了这么多,我们来看看一棵红黑树到底如何构造出来的吧,通过通话来加深理解。

红黑树性能分析

所有基于红黑树的符号表实现都保证操作的运行时间为对数级别!

因为,不论插入的顺序如何,红黑树都几乎是完美平衡的

不管是在随机情况下

还是在最坏的情况下,红黑树的深度也不会超过2logN

红黑树更吸引人的一点在于,基本除了put和delete算法比较复杂,其他的代码,都可以直接使用二叉树的代码。

时间: 2024-10-17 11:31:18

《 常见算法与数据结构》平衡查找树(2)——红黑树(附动画)的相关文章

浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树

http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的时候具有较高的灵活性,而有序数组在查找时具有较高的效率,本文介绍的二叉查找树(Binary Search Tree,BST)这一数据结构综合了以上两种数据结构的优点. 二叉查找树具有很高的灵活性,对其优化可以生成平衡二叉树,红黑树等高效的查找和插入数据结构,后文会一一介绍. 一 定义 二叉查找树(B

浅谈算法和数据结构: 九 平衡查找树之红黑树

原文:浅谈算法和数据结构: 九 平衡查找树之红黑树 前面一篇文章介绍了2-3查找树,可以看到,2-3查找树能保证在插入元素之后能保持树的平衡状态,最坏情况下即所有的子节点都是2-node,树的高度为lgN,从而保证了最坏情况下的时间复杂度.但是2-3树实现起来比较复杂,本文介绍一种简单实现2-3树的数据结构,即红黑树(Red-Black Tree) 定义 红黑树的主要是像是对2-3查找树进行编码,尤其是对2-3查找树中的3-nodes节点添加额外的信息.红黑树中将节点之间的链接分为两种不同类型,

【转】浅谈算法和数据结构: 九 平衡查找树之红黑树

http://www.cnblogs.com/yangecnu/p/3627386.html 前面一篇文章介绍了2-3查找树,可以看到,2-3查找树能保证在插入元素之后能保持树的平衡状态,最坏情况下即所有的子节点都是2-node,树的高度为lgN,从而保证了最坏情况下的时间复杂度.但是2-3树实现起来比较复杂,本文介绍一种简单实现2-3树的数据结构,即红黑树(Red-Black Tree) 定义 红黑树的主要是像是对2-3查找树进行编码,尤其是对2-3查找树中的3-nodes节点添加额外的信息.

算法5-1:平衡查找树之二三树

平衡查找树的目标是实现查找.插入.删除操作在最坏情况下的复杂度均为logN. 本节将介绍二三查找树. 二三树中有两种节点: 二节点对应一个键,有两个子节点 三节点对应两个键,有三个子节点 二三查找树非常平衡,每个空节点到根节点的距离都是一样的 . 查找操作 在二三树中查找一个键的时候有以下规则: 如果是二节点,二节点对应1个值,如果要查找的值比该节点对应的值小,就往左侧深入,反之亦成 如果是三节点,三节点对应2个值,如果比两个值都小,就往左侧深入,如果介于两个值之间,就往中间深入,如果比两个值都

《 常见算法与数据结构》平衡查找树(1)—— 2-3查找树(附动画)

本系列文章主要介绍常用的算法和数据结构的知识,记录的是<Algorithms I/II>课程的内容,采用的是"算法(第4版)"这本红宝书作为学习教材的,语言是java.这本书的名气我不用多说吧?豆瓣评分9.4,我自己也认为是极好的学习算法的书籍. 通过这系列文章,可以加深对数据结构和基本算法的理解(个人认为比学校讲的清晰多了),并加深对java的理解. 2-3树介绍 我们上回说到二叉查找树已经很接近我们的目标了,在很多情况下性能都很不错,但是唯独在删除上不行,一旦删除操作做

转 浅谈算法和数据结构: 十 平衡查找树之B树

前面讲解了平衡查找树中的2-3树以及其实现红黑树.2-3树种,一个节点最多有2个key,而红黑树则使用染色的方式来标识这两个key. 维基百科对B树的定义为"在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据.对其进行排序并允许以O(log n)的时间复杂度运行进行查找.顺序读取.插入和删除的数据结构.B树,概括来说是一个节点可以拥有多于2个子节点的二叉查找树.与自平衡二叉查找树不同,B-树为系统最优化大块数据的读和写操作.B-tree算法减少定位记录时所经历的中间过程,从而

浅谈算法和数据结构: 十 平衡查找树之B树

转载自 http://www.cnblogs.com/yangecnu/p/3632027.html 浅谈算法和数据结构: 十 平衡查找树之B树 前面讲解了平衡查找树中的2-3树以及其实现红黑树.2-3树种,一个节点最多有2个key,而红黑树则使用染色的方式来标识这两个key. 维基百科对B树的定义为“在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据.对其进行排序并允许以O(log n)的时间复杂度运行进行查找.顺序读取.插入和删除的数据结构.B树,概括来说是一个节点可以拥

[转]浅谈算法和数据结构: 八 平衡查找树之2-3树

前面介绍了二叉查找树(Binary Search Tree),他对于大多数情况下的查找和插入在效率上来说是没有问题的,但是他在最差的情况下效率比较低.本文及后面文章介绍的平衡查找树的数据结构能够保证在最差的情况下也能达到lgN的效率,要实现这一目标我们需要保证树在插入完成之后始终保持平衡状态,这就是平衡查找树(Balanced Search Tree).在一棵具有N 个节点的树中,我们希望该树的高度能够维持在lgN左右,这样我们就能保证只需要lgN次比较操作就可以查找到想要的值.不幸的是,每次插

平衡查找树

一.2-3查找树 二叉查找树可以使用于大多数应用场景,但是最坏情况下性能太差. 本节将介绍一种二分查找树,它的运行时间可以保证在对数级别内. 1.定义 这里引进3-节点的概念,3-节点含有两个键和三个链接. 2-节点是标准二叉查找树中的节点,含有一个键和两个链接. Definition. A 2-3 search tree is a tree that either is empty or: A 2-node, with one key (and associated value) and tw