目录
①:向2-3树的2节点添加元素(分为插入的元素是左孩子还是右孩子)
②:向2-3树中的3节点添加元素(也分为插入左孩子和右孩子)
一、为什么要学习红黑树?
首先,我们知道二分搜索树存在缺陷,就是如果插入的元素是顺序的则二分搜索树就变成和链表一样了,这样就会带来性能问题。
为了改变上图中的情况,就出现了AVL平衡二叉树,在平衡二叉树中规定了一个节点的左右孩子高度之差不能超过1,如果当插入或者删除了节点导致左右孩子高度差超过了1,就需要进行左旋或者右旋操作进行调整,总之平衡二叉树的性值保证了树中的节点不会出现上图,这样也就保证了其查询的时间复杂度为logn。
那么平衡二叉树在我们看来已经很优秀了,为什么还会有红黑树这种树结构出现呢?这是由于尽管AVL平衡树的查询效率非常高,但是有利就有弊,AVL树为了维持绝对的平衡(左右孩子高度差不超过1),就要符出更多的代价,每次插入、删除都可能需要进行调整以保证平衡,所以这就降低了插入、删除操作的性能,对于频繁的插入、删除的数据集合,如果使用AVL树代价就有点高了。
这时红黑树就出现了,红黑树仅仅是做到了近似平衡,没有达到严格意义上左右孩子高度差不能大于1,所以在维护平衡的成本上,红黑树远低于AVL树,也因此红黑树的插入、删除的性能会优于AVL,并且由于红黑树的近似平衡所以在查询上与AVL的性能相差不大。对于在真正上线的项目而言,需要面对各种异常情况,为了更好的满足项目各项性能,我们就更倾向于选择这种性能各方面比较稳定的红黑树,这就是我们为什么学习红黑树的原因。
二、红黑树的基本介绍
如果要想学习红黑树,建议先学习一下2-3树【数据结构】图解2-3树(学习红黑树、B树的基础)
让我们回顾一下2-3树,如下图,2-3树的所有节点只能是下图的这两种形式。
那么红黑树和2-3树具有怎样的关系呢。上图的2-3树形式对应于红黑树中就是下图。
接下来再看一个较为复杂的2-3树及其对应的红黑树。
看了上面的图就会发现,其实红黑树和2-3树本质上是等价的,只不过对于2-3树中的3节点表现得形式用红色表示了出来(红色节点只能是左侧),接下来我们就来简单介绍一下红黑树.
R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。
红黑树的特性::
- (1)每个节点或者是黑色,或者是红色
- (2)根节点是黑色
- (3)每个叶子节点(最后的空节点)是黑色
- (4)如果一个节点是红色的,则它的子节点必须是黑色的
- (5)从任意一个节点到叶子节点,经过的黑色节点是一样的 (对应着2-3树看,因为2-3树是绝对平衡的)
红黑树的最大高度为2logn我们试着分析一下为什么红黑树最大高度是2logn?
因为在最次的情况下从根节点到最深的叶子节点,我们经历了logn个黑色节点,但同时这些黑色节点的左子树也可能都有红色节点,这就形成了2logn.
三、图解+代码实现红黑树添加元素流程
首先我们回忆一下2-3树是如何添加元素的,2-3树永远不会把添加的元素放到叶子节点(根节点除外),而是把添加的节点与已有节点进行融合,对于红黑树而言,其实红色的节点就代表之前该节点在2-3树中是融合在一起的。因此对于新添加的元素我们把它设置成红色。(红黑树规定,插入的节点必须是红色的,学习红黑树脑子一定要记着2-3树的性质)
下面我们就对红黑树进行一个基本的构建,并且保证新插入的元素是红色的、根节点始终是黑色的。
定义了两个final变量使用布尔类型来表示红色和黑色,在每次新创建一个元素的时候调用无参构造方法都会将其颜色设置为红色
public class RBTree<E extends Comparable<E>> {
private static final boolean RED = true;
private static final boolean BLACK = false;
private class Node {
public E e;
public Node left, right;
public boolean color;
public Node(E e) {
this.e = e;
left = null;
right = null;
color = RED;
}
}
private Node root;
private int size;
public RBTree() {
root = null;
size = 0;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
private boolean isRed(Node node){
if(node == null)
return BLACK;
return node.color;
}
</