底层实现数据结构:红黑树

目录



整体结构思维导图


在这里插入图片描述

-------------------------------------------------------------------------------- 回到目录

什么是2-3树


2-3树:满足二分搜索树的基本性质,节点可存放一个元素或两个元素,是一棵绝对平衡的树(任意子树左右高度差为0)。
在这里插入图片描述

2-3树插入元素

一个原则: 添加节点将永远不会添加到一个空的位置(这和二叉搜索树不同),只会和最后找到的叶子节点做融合。

添加方法:
0、从根节点开始寻找到要插入的父亲节点。

1、若节点小于父亲节点,就融合到左边,大的就融合到右边。

2、若融合完后父亲节点变成4节点(父亲节点有3个元素,4个孩子),就把父亲节点从中间元素分裂,否则完成当前节点的添加。

3、若分裂完后的父亲节点的父亲节点不是4节点,就重复1、2步骤。

分裂图示:
初级图示:
在这里插入图片描述
中级图示:
在这里插入图片描述
高级图示:
在这里插入图片描述

-------------------------------------------------------------------------------- 回到目录

2-3树与红黑树关系

2-3树与红黑树是等价的,红黑树只不过是在2-3树的基础上做一些人为规则的约定:

以下实现的红黑树是左倾红黑树。

关于颜色:
2节点都是黑色,3节点中小的元素红色,大的元素黑色:(即红色节点永远左倾)
在这里插入图片描述
完整图示:
在这里插入图片描述
上图直观的图示:
在这里插入图片描述

-------------------------------------------------------------------------------- 回到目录

红黑树性质


在这里插入图片描述
1-4点可对照上上图的图示理解,重点是第5点。

第5点: 其最主要的原因是2-3树是绝对平衡的,其次是每个3节点都有一个黑色节点,所以不管怎么走经过的黑色节点的数量是一样多的。

所以红黑树是保持"黑平衡"的二叉树,本质就是2-3树是绝对平衡的。

红黑树严格意义上并不是平衡二叉树,因为平衡因子有可能大于1,但因为“黑平衡”的存在,所以也可看成是平衡二叉树。

红黑树添加元素


首先,新插入的节点永远是红色的。 空节点是黑色的。

添加步骤:
0、从根节点开始寻找到要插入的父亲节点,若是插入第一个节点,则插入后变成黑色。

1.1、若父亲节点没有左孩子,则:
若节点小于父亲节点,则插入到左孩子,保持红色不变;
(插入后左黑,右黑)(保持不变)

若节点大于父亲节点,则插入到右孩子后进行左旋转,对孩子节点和父亲节点进行变颜色,红色变黑色,黑色变红色。
(插入后左黑,右红)(左旋转)

1.2、若父亲节点有左孩子,则:
1.2.1 若节点小于父亲节点的左孩子,则插入到父亲节点的左孩子的左孩子,(a)然后进行右旋转,把父亲节点和父亲节点的左孩子进行变颜色,再把3个节点进行颜色翻转。
(插入后左红,左左红)(右旋转)(颜色翻转)

1.2.2 若节点大于父亲节点的左孩子,则插入到父亲节点的左孩子的右孩子,然后进行左旋转,再进行(a)步骤。
(插入后父亲节点的左孩子左黑,右红)(左旋转)(右旋转)(颜色翻转)

1.2.3 若节点大于父亲节点,则插入到右孩子,然后3个节点进行颜色翻转。
(插入后左红,右红,自己黑)(颜色翻转)
在这里插入图片描述

-------------------------------------------------------------------------------- 回到目录
可以看下面添加元素的代码加深添加过程的理解。

添加元素的代码:

     /** 向红黑树中添加新的元素(key, value) */
    public void add(K key, V value) {
   //相当于JDK的put操作
        root = add(root, key, value);
        root.color = BLACK; /**子过程一: 保持最终根节点为黑色  --> 第二条性质 */
    }

    // 向以node为根的红黑树树中插入元素(key, value),递归算法,返回插入新节点后红黑树树的根
    private Node add(Node node, K key, V value) {
   

        if (node == null) {
   
            size++;
            return new Node(key, value);
        }

        if (key.compareTo(node.key) < 0)
            node.left = add(node.left, key, value);
        else if (key.compareTo(node.key) > 0)
            node.right = add
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值