前言
相信真正热爱java的开发者们,都读过java版的数据结构和算法,还没读过的java粉们,也在买书和搜索资料的路上(想找还没找到的小伙伴们,也可以@Elean说“我要”)。大家都知道,在实际开发中,HashMap的应用场景很常见,因此,它也成了招聘中很多面试官的钟爱。如果你说,你对它的底层原理没有做深入了解还好,但如果你说有看过,那么不好意思,你入坑了,挖呀挖呀挖呀,总会给你挖出个“红黑树”。强扭的瓜不甜,硬记的脸易忘。再加上面试官一副问到你主动降工资的不罢休,总会有办法让你只记得它是一个平衡二叉树(亲身体验,不扯淡)。由此,笔者想通过手敲红黑树源码,加深下对它的记忆。但是笔者看的资料里只有对红黑树的描述,没有demo,只能找出HashMap里的源码,一丢一丢的还原了,不易呀!
一、基本原则
1.1 平衡二叉树
先来复习一下平衡二叉树
概念:任何节点的左右子树的高度差的绝对值小于1,
优点:保证了查找性能的O(log2n),避免出现二叉树变成了链表的极端情况
缺点:插入的时候需要通过旋转等手段保持二叉树的平衡性
可以看出,平衡二叉树是将树的优点挖掘出来的一种手段,那么红黑树是如何做的呢?
1.2 红黑树
红黑树的基本原则:
1) 每一个节点不是红色的就是黑色的(废话不用记)
2) 根总是黑色的(铁律:发言就要举手)
3) 如果节点是红色的,则它的子节点必须是黑色的(反之不一定为真)
4) 从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点
无规矩不成方圆,3)、4)两条原则是保证构造出的树是红黑树的根本。至于2)是为了处理只需要变换颜色就能符合红黑树原则的情况时减少颜色变换的次数。笔者自己经过几次颜色变换的尝试,发现颜色变换最终会限制再根节点的单个分支,即,根节点的左分支发生颜色变换,不会蔓延到右分支(这是笔者自己的理解,欢迎老铁们拿真理怼我😂)。
二、代码实现
2.1 属性
在存储器上,存储的分布方式对应了集合数据的两种分布,一种是连续的,对应我们的数组,另一种是分散的,可以对应我们的链表结构。由此,树和图等的实现也是基于这两种基本结构。我们本次还是使用链表结构,一是数组实现的方式容易混淆,另外也是为了跟HashMap中保持一致。一个最基本的树节点应该包含节点值,左子节点应用,右子节点引用,父节点引用,红黑标志,其中节点值我们也跟HashMap中一样用hash表示,以便于在以后编写自定义HashMap的文章时能够在此基础上扩展。
属性:
package com.elean.map;
/**
*