红黑树简介
在介绍红黑树之前,首先我们要知道什么叫二叉搜索树。
二叉搜索树的性质:
首先是一个二叉树,其次其左子树的值小于其父结点的值,右子树的值大于父节点的值。我们知道树这种数据结构非常适合做搜索,例如数据库的索引也是基于B+树实现的,二叉搜索树的插入,删除,搜索,一般的时间复杂度是O(log(n)).,如下图是一个标准的二叉搜索树,
但是极端情况下有可能退化成链表。时间复杂度变为O(n).
而红黑树在er二叉平衡搜索树的基础上改良而成。
红黑树具有良好的效率,它可在 O(logN) 时间内完成查找、增加、删除等操作。比如 Java 中的 TreeMap,JDK 1.8 中的 HashMap、C++ STL 中的 map 均是基于红黑树结构实现的。
红黑树有五个性质:
性质1:节点是红色或黑色。
性质2:根节点是黑色。
性质3: 每个叶节点(NIL节点,空节点)是黑色的。
性质4: 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质5: 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
由于性质4和性质5导致红黑树从根节点到叶子节点的最长路径不是比最短路径多于2倍。
红黑树的操作
当插入或删除树中节点时,需要通过变色,左旋,右旋操作来使红黑树重新达到平衡。
1.变色
下图是插入节点时的调整树的一种情况,通过变色来调整
2.旋转(左旋转和右旋转)
左旋转:比如当前节点为P,P的左孩子为N,右孩子为S,将当前节点的右孩子替换自身的位置,原右孩子的左子孩子成为其原父节点的右子孩子。完成左旋。
右旋转:将当前节点的左孩子孩子替换自身的位置,原左孩子的右子孩子成为其原父节点的左子孩子。完成右旋。
插入
红黑树先按照二叉搜索树的插入规则插入新节点,不同点在于插入新的节点之后红黑树的性质会被破坏,红黑树的树结构需要重新调整,
红黑树插入的新节点都是红色节点,为什么不插入黑色的节点呢?因为插入红色节点调整起来比黑色节点容易。如果插入黑色节点,直接就破坏了性质5,该条路径会多出一个黑色节点,如果插入的是一个红色节点,如果其父节点是黑色,则不需要调整。如果其父节点时红色,则其违反性质4,则开始调整红黑树(以下节点为白色代表其节点及后续节点暂且不画)
1.情况1
如果该树是一颗空树,则将新插入的节点变为黑色。
2.情况2
如果其父节点是黑色,则不需要调整,
3.情况3
当其父节点为红色,其叔叔节点为红色,那么其爷爷节点为黑色,那么通过将其父亲和其叔叔变为红色,再将其爷爷变为红色,但是其G节点变为红色之后,有可能会和其G的父节点形成连续的红色节点,这种情况需要按照递归调整。
4.情况4
这里情况4的出现,这里的N不一定时新插入的节点有可能是情况2调整完导致的,当N的叔叔节点为黑色,N为其右孩子时,将P节点进行左旋,然后按照情况5进行调整
5.情况5
N的叔叔节点U为黑色,且其父节点P是G的左孩子,将P和G互换颜色,然后将G节点进行右旋,此刻红黑树恢复平衡。
插入总结
新节点插入时为红色节点,只有其父节点是红色节点时才需要调整。
而其爷爷节点必为黑色节点,当其叔叔节点为红色,则采取情况二进行调整,情况二调整之后如果,与其父节点形成连续的红色点,则递归调整,下次按照情况4调整,情况4调整完会出现情况5,情况5调整完树必然平衡,下面我们结合treeMap源码分析一下
下面是其节点的构成
static final