插入与Java代码实现-红黑树-数据结构和算法

插入与Java代码实现-红黑树-数据结构和算法

目录




内容

1、前期分析

  • 红黑树插入节点过程大致分析:

    1. RBTree为二叉搜索树,我们按照二叉搜索树的方法对其进行节点插入
    2. RBTree有颜色约束性质,因此我们在插入新节点之后要进行颜色调整
  • 新节点颜色调整

当红黑树插入新节点后,有可能破坏红黑树的特性,变成一棵普通的树。这时候我需要进行调整,为了尽可能的减少工作量, 我们通过观察发现其中,红黑树的前3条特性是不会违反的;为了符合第5条特性,我们一般把新节点的颜色设置为红色;那么剩下就只可能是违反第4条规定,既从每个叶子到根的所有路径上不能有两个连续的红色结点。我们接下来的调整,只需要关注这点就可以了。

2、插入步骤

根据给定信息,创建新节点,颜色为红色。

2.1、红黑树为空

  1. 根节点root指向该节点,节点颜色设置黑色

2.2、按照二叉搜索树的方法对其进行节点插入

2.3、对红黑树进行平衡调整

3、平衡性调整

  1. 获取目标节点x的父节点xp,如何xp为空,说明x为根节点,把节点x颜色设置为黑色(性质2)调整结束

  2. 如果xp节点颜色为黑色或者获取xp的父节点xpp,如果xpp为空,调整结束

  3. 如何不符合情况1,2,那么现在条件 xp非空红色,xpp非空。xp可能是xpp的左节点或者右节点,我们以左节点为例。

  4. xp为xpp的左节点,如果xpp的右节点xppr不为空且颜色为红色,那么xpp一定为黑色(性质4)

    1. 那么节点xp,xppr 颜色设置为黑色
    2. xpp设置为红色
    3. 把xpp赋值给当前节点x
    4. 图示:在这里插入图片描述
    • 目标就是把红色节点网根节点方向转移
  5. xp为xpp的左节点,且不满足条件4

    1. 如果x为xp的右节点,那么通过节点xp左旋,xp设置为当前节点x,以满足下面条件5.2

      • 图示:在这里插入图片描述
    2. 此时如果xp不为空,xp颜色设置为黑色,如何xpp也不为空,xpp颜色设置为红色,对节点xpp右旋

      • 图示:在这里插入图片描述
  6. xp为xpp的右节点同理,这里不再详述

  7. 重复以上步骤,知道满足条件1或者2退出循环

4、Java代码实现

  • 插入代码
// 插入
    public V add(K k, V v) {
        if (k == null) return null;
        RBNode<K, V> n = new RBNode<>(k, v, true, null, null, null);
        if (root == null) {
            n.red = false;
            root = n;
            size = 1;
            return v;
        }
        RBNode<K, V> pp = null;
        RBNode<K, V> p = root;
        while (p != null) {
            if (((Comparable) k).compareTo(p.key) < 0) {
                pp = p;
                p = p.left;
            } else if (((Comparable) k).compareTo(p.key) > 0) {
                pp = p;
                p = p.right;
            } else {
                V value = p.value;
                p.value = v;
                return value;
            }
        }
        n.parent = pp;
        if (((Comparable) k).compareTo(pp.key) < 0)
            pp.left = n;
        else
            pp.right = n;
        root = balanceInsertion(root, n);
        size++;
        return v;
    }
  • 插入后平衡性调整代码
// 插入后平衡调整
    static <K, V> RBNode<K, V> balanceInsertion(RBNode<K, V> root, RBNode<K, V> x) {
        x.red = true;
        for (RBNode<K, V> xp, xpp, xppl, xppr; ; ) {
            if ((xp = x.parent) == null) {
                x.red = false;
                return x;
            } else if (!xp.red || (xpp = xp.parent) == null)
                return root;
            if (xp == (xppl = xpp.left)) {
                if ((xppr = xpp.right) != null && xppr.red) {
                    xp.red = xppr.red = false;
                    xpp.red = true;
                    x = xpp;
                } else {
                    if (x == xp.right) {
                        root = rotateLeft(root, x = xp);
                        xpp = (xp = x.parent) == null ? null : xp.parent;
                    }
                    if (xp != null) {
                        xp.red = false;
                        if (xpp != null) {
                            xpp.red = true;
                            root = rotateRight(root, xpp);
                        }
                    }
                }
            } else {
                if (xppl != null && xppl.red) {
                    xppl.red = xp.red = false;
                    xpp.red = true;
                    x = xpp;
                } else {
                    if (x == xp.left) {
                        root = rotateRight(root, x = xp);
                        xpp = (xp = x.parent) == null ? null : xp.parent;
                    }
                    if (xp != null) {
                        xp.red = false;
                        if (xpp != null) {
                            xpp.red = true;
                            root = rotateLeft(root, xpp);
                        }
                    }
                }
            }

        }
    }

5、测试及打印

  • 测试代码:
public static void testRBTree() {
        RBTree<Integer, String> rbTree = new RBTree<>();
        rbTree.add(1, "aaa");
        rbTree.add(23, "sdf");
        rbTree.add(63, "434");
        rbTree.add(634, "r4f");
        rbTree.add(223, "2342");
        rbTree.add(22, "fwff");
        System.out.println(rbTree);
        System.out.println(rbTree.size());
//        rbTree.removeRBTreeNode(63);
//        System.out.println(rbTree);
//        System.out.println(rbTree.size());
    }
	
	// 打印结果
	[(1,aaa,黑),(22,fwff,红),(23,sdf,黑),(63,434,红),(223,2342,黑),(634,r4f,红)]
	6
  • 参考地址
  1. Jdk HashMap TreeNode
  2. 浅析红黑树(RBTree)原理及实现

后记

  欢迎交流,本人QQ:806797785

项目源代码地址:https://gitee.com/gaogzhen/algorithm.git
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gaog2zh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值