《算法 Algorithms 第四版》红黑树学习小结

序言

在2-3查找树中的3-结点的表示和代码实现上会比较麻烦,所有使用红黑二叉查找树来将二叉查找树和2-3查找树综合起来,实现高效的查找和插入等操作
我们将3-结点的两个键变成两个2-结点,并用一条红链接将其链接起来,在形式上满足了二叉查找树,概念上满足2-3查找树。

这里是引用

红黑树的另一种定义时含有红黑链接并满足下列条件的二叉查找树:

  1. 红链接均为左链接;
  2. 没有任何一个结点同时和两条红链接相连;
  3. 该树时完美黑色均衡的,即任意空连接到根结点的路径上的黑链接数量相同

旋转

旋转分为左旋转和右旋转(重点理解)
左旋转
当红黑树中出现一条右链接为红链接时,我们要进行左旋转,左旋转我的理解是以根节点E为轴心,逆时针的将这条红链接旋转90度变成左链接,此时原来的根结点E变成了现在左链接的左子结点,原来的右子结点S变成了现在的根结点。
如果原来的右链接的右子结点S有自己的左子结点,则将该左子结点(S的左子结点)连接到现在的红链接的左子结点(E)的右链接上。
在这里插入图片描述
右旋转
当红黑树中需要将左链接旋转时,我们要进行右旋转,右旋转我的理解是以结点E为轴心,顺时针的将这条红链接旋转90度变成右链接,此时原来的根结点S变成了现在右链接的右子结点,原来的左子结点E变成了现在的根结点。
如果原来的左链接的左子结点E有自己的右子结点,则将该右子结点(E的右子结点)连接到现在的红链接的右子结点(S)的左链接上。
在这里插入图片描述

插入操作

插入操作分别有5个操作,其中操作一、二、三、四结合左旋转和右旋转构成了构建一颗红黑树的关键步骤,一定要理解。
操作一:向单个2-结点中插入新键
如果新键小于这个2-结点,我们将新键插入到2-结点的左链接中,并将链接变成红链接;如果大于该结点,则先构建一个右链接,然后左旋转,构造一个左红链接。

在这里插入图片描述在这里插入图片描述

操作二:向树底部的2-结点插入新键
为了保证有序性,总是用红链接将新结点和它的父结点相连。(这句话是构建红黑查找树的基石)如果出现了右链接需要左旋转一次。
操作三:向一颗双键树(即一个3-结点)中插入新键
这里一共分为3中情况:
情况一 新键最大
在这里插入图片描述
情况二 新键最小
在这里插入图片描述
情况三 新键介于两者之间
在这里插入图片描述
操作四:颜色变换
当一个结点的左链接和右链接均为红色时,需要将左右链接变为黑色然后将链接这个结点的链接变为红色

这里是引用

操作五:向树底部的3-结点插入新键
这个操作其实是操作三和操作二的以及相应的旋转的结合
在这里插入图片描述

代码实现

public void put(Key key, Value val) {
        if (key == null) throw new IllegalArgumentException("first argument to put() is null");
        if (val == null) {
            delete(key);
            return;
        }

        root = put(root, key, val);
        root.color = BLACK;
        // assert check();
    }

    // insert the key-value pair in the subtree rooted at h
    private Node put(Node h, Key key, Value val) { 
        if (h == null) return new Node(key, val, RED, 1);

        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              h.val   = val;

        // fix-up any right-leaning links
        if (isRed(h.right) && !isRed(h.left))      h = rotateLeft(h);
        if (isRed(h.left)  &&  isRed(h.left.left)) h = rotateRight(h);
        if (isRed(h.left)  &&  isRed(h.right))     flipColors(h);
        h.size = size(h.left) + size(h.right) + 1;

        return h;
    }

测试用例

这里是引用

以左侧的插入为例,插入E结点时,用的时操作一,插入A结点时运用的是操作三。
插入H时,先是用操作二将H结点插入到R的左链接上,这时S、R、H三个结点出现了两条红色链接,运用右旋转后再用操作四将E链接R的链接变成右红链接,然后进行左旋转就变成了图中所示插入H后红黑树的样子。

注释:本文引用的图片均来自于《算法 Algorithms 第四版》一书提供的官方网站https://algs4.cs.princeton.edu,若有需要请注明来源!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值