HashMap中红黑树操作实现

本文详细介绍了红黑树操作方法的实现,包括左旋、右旋和平衡插入与删除等核心步骤,确保数据结构保持平衡状态。
 // 红黑树操作方法实现, 从CLR引入

        static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root,
                                              TreeNode<K,V> p) {        //左旋
            TreeNode<K,V> r, pp, rl;
            if (p != null && (r = p.right) != null) {
                if ((rl = p.right = r.left) != null)
                    rl.parent = p;
                if ((pp = r.parent = p.parent) == null)
                    (root = r).red = false;
                else if (pp.left == p)
                    pp.left = r;
                else
                    pp.right = r;
                r.left = p;
                p.parent = r;
            }
            return root;
        }

        static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root,
                                               TreeNode<K,V> p) {            //右旋
            TreeNode<K,V> l, pp, lr;
            if (p != null && (l = p.left) != null) {
                if ((lr = p.left = l.right) != null)
                    lr.parent = p;
                if ((pp = l.parent = p.parent) == null)
                    (root = l).red = false;
                else if (pp.right == p)
                    pp.right = l;
                else
                    pp.left = l;
                l.right = p;
                p.parent = l;
            }
            return root;
        }

        static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root,
                                                    TreeNode<K,V> x) {        //插入后调整平衡
            x.red = true;
            for (TreeNode<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) {
                        xppr.red = false;
                        xp.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 = false;
                        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);
                            }
                        }
                    }
                }
            }
        }

        static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root, TreeNode<K,V> x) {    //删除后调整平衡
            for (TreeNode<K,V> xp, xpl, xpr;;)  {
                if (x == null || x == root)
                    return root;
                else if ((xp = x.parent) == null) {
                    x.red = false;
                    return x;
                }
                else if (x.red) {
                    x.red = false;
                    return root;
                }
                else if ((xpl = xp.left) == x) {
                    if ((xpr = xp.right) != null && xpr.red) {
                        xpr.red = false;
                        xp.red = true;
                        root = rotateLeft(root, xp);
                        xpr = (xp = x.parent) == null ? null : xp.right;
                    }
                    if (xpr == null)
                        x = xp;
                    else {
                        TreeNode<K,V> sl = xpr.left, sr = xpr.right;
                        if ((sr == null || !sr.red) &&
                            (sl == null || !sl.red)) {
                            xpr.red = true;
                            x = xp;
                        }
                        else {
                            if (sr == null || !sr.red) {
                                if (sl != null)
                                    sl.red = false;
                                xpr.red = true;
                                root = rotateRight(root, xpr);
                                xpr = (xp = x.parent) == null ?
                                    null : xp.right;
                            }
                            if (xpr != null) {
                                xpr.red = (xp == null) ? false : xp.red;
                                if ((sr = xpr.right) != null)
                                    sr.red = false;
                            }
                            if (xp != null) {
                                xp.red = false;
                                root = rotateLeft(root, xp);
                            }
                            x = root;
                        }
                    }
                }
                else { // symmetric
                    if (xpl != null && xpl.red) {
                        xpl.red = false;
                        xp.red = true;
                        root = rotateRight(root, xp);
                        xpl = (xp = x.parent) == null ? null : xp.left;
                    }
                    if (xpl == null)
                        x = xp;
                    else {
                        TreeNode<K,V> sl = xpl.left, sr = xpl.right;
                        if ((sl == null || !sl.red) &&
                            (sr == null || !sr.red)) {
                            xpl.red = true;
                            x = xp;
                        }
                        else {
                            if (sl == null || !sl.red) {
                                if (sr != null)
                                    sr.red = false;
                                xpl.red = true;
                                root = rotateLeft(root, xpl);
                                xpl = (xp = x.parent) == null ?
                                    null : xp.left;
                            }
                            if (xpl != null) {
                                xpl.red = (xp == null) ? false : xp.red;
                                if ((sl = xpl.left) != null)
                                    sl.red = false;
                            }
                            if (xp != null) {
                                xp.red = false;
                                root = rotateRight(root, xp);
                            }
                            x = root;
                        }
                    }
                }
            }
        }



### Java 中 HashMap 使用红黑树的情况及其工作机制 #### 一、HashMap 的桶结构 在 JDK 1.8 及之后版本中,`HashMap` 的底层实现由数组和链表组成。当某个桶中的链表长度达到一定阈值时,为了提高查找效率,链表会被转换为红黑树[^1]。 具体来说,`TREEIFY_THRESHOLD` 是决定是否将链表转为红黑树的关键参数,默认值为 **8**。这意味着如果某一个桶内的节点数量超过或等于 8,则会触发 `treeifyBin` 方法,尝试将此链表转换成红黑树[^5]。 然而需要注意的是,只有当哈希表的容量大于等于 **64** 时才会执行上述操作;否则会选择扩容而不是直接构建红黑树[^3]。这是因为对于较小规模的数据集而言,扩容通常比维护复杂的树形结构更高效。 #### 二、红黑树的工作机制 ##### (1)基本概念 红黑树是一种特殊的二叉搜索树(BST),具有以下几个特性来保持动态平衡状态: - 每个结点要么是红色要么是黑色; - 根总是黑色; - 如果一个内部节点存在子节点的话那么这些孩子都不能为空白叶子(nil); - 对于任何给定路径上的所有简单路径从该顶点到后代叶之间经过相同数目黑节点的数量相等; - 不允许连续两个红色节点相邻出现即父与儿子不能同为red color. 以上性质共同作用使得整个数据结构能够在O(log n)时间内完成增删改查等各种基础运算[^2]. ##### (2)自平衡调整过程概述 每当向一棵已存在的RB Tree 插入新元素或者移除已有成员后都需要重新审视当前整体布局是否存在违反前述规则之处并采取相应措施予以修正包括但不限于旋转(spinning)以及颜色翻转(color flipping): ###### A). 插入后的修复流程可能涉及以下几种情况处理: * Case I: 新加入者作为唯一根部无需额外动作; * Case II~VII : 需要根据不同上下文环境分别应用左旋/右旋配合变色策略直至恢复合法形态为止. ###### B). 删除过程中也可能引发局部失衡现象同样需借助类似手段加以解决: 通过一系列精心设计好的算法步骤最终达成全局稳定目的同时兼顾性能表现方面的要求. #### 三、代码片段展示 以下是部分核心逻辑摘录用于辅助理解: ```java // 判断是否需要将链表转化为红黑树 if (binCount >= TREEIFY_THRESHOLD - 1) { treeifyBin(tab, hash); } private final void treeifyBin(Node<K,V>[] tab, int hash) { ... } ``` 此外还有关于如何初始化实例化对象等内容也可以参阅如下构造函数定义样例: ```java public HashMap(Map<? extends K, ? extends V> m){ this.loadFactor = DEFAULT_LOAD_FACTOR; putMapEntries(m,false); } ``` 这里体现了默认装载因子设定为0.75的同时还支持批量导入外部映射关系等功能特点[^4].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值