目录
1.红黑树的的由来
1.1 二叉查找树
二叉查找树是一种方便查找数据的树,它在满足二叉树的特性上,拥有一个特性,那就是二叉查找树中任意一个节点,它的左子节点小于这个节点,它的右子节点大于这个节点。它正常的查找效率是O(logn),但也会出现一种极端的情况,那就是二叉查找树有可能会退化成链表,为了防止这种情况的出现,就出现了AVL树(平衡二叉树)。
1.2AVL树(平衡二叉树)
AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为平衡二叉树。虽然平衡二叉树不会出现退化成链表的情况,但是平衡二叉树的平衡特性很容易被破坏,当插入一个节点导致破坏了平衡二叉树左右子树的高度差大于一的时候,就需要进行调整,这样就会很繁琐,所以在综合了二叉查找树和平衡二叉查找树的基础上形成了红黑树。下面是平衡二叉树和非平衡二叉树对比的例图:
1.3红黑树
红黑树它是一种特殊的二叉查找树,它的每一个节点的颜色是红色或者黑色。红黑树如下图所示
2.红黑树的特性
(1).如果一个节点拥有左右子节点,那它的左节点K一定会小于这个节点的K,右子节点的K一定大于这个节点的K。
(2).节点颜色要么是红色,要么是黑色。
(3).如果根节点不为空,那么它的根节点一定是黑色,它的叶子节点NIL一定是黑色。
(4).不能出现两个相连的节点都是红色的情况,如果一个节点是红色,那么它的左右子节点一定是黑色。
(5).从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。这个特性确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树。
3.红黑树的左旋和右旋
为什么需要对红黑树进行左旋或者右旋,这是因为当插入一个节点或者删除一个节点后,红黑树已经不满足红黑树的特性了,所以需要对红黑树进行调整。
3.1 红黑树的左旋
那下面的图来说对x节点进行左旋:
总结一下上面x节点的操作,首先会将x右子树y的左节点变成x节点的右子树,然后让x节点变成x节点右子树的左子树。其实就是这个节点的右子树替代这个节点的位置,然后让右子树的左子树变成自己的右子树。一个节点左旋的话,它会下降一层。
3.2红黑树的右旋
那下面的图来说对x节点进行右旋:
总结一下x节点的右旋,使得父节点被自己的左孩子取代,而自己成为自己的右孩子的右节点,然后左孩子的右节点成为自己的左节点。
总结一下左右旋
左旋就是自己被自己的右子节点替代,自己变成右子节点的左子节点,自己以前的右子节点的左子树变成了自己的右子树。
右旋就是自己被自己的左子节点替代,自己变成左子节点的的右子节点,自己以前的左子节点的右子树变成自己的左子树。
4.红黑树的插入
红黑树的插入通常会通过变色和左旋或者右旋来处理,这样让插入节点后依然能满足红黑树的特性。红黑树每一次插入的节点都是红色,为什么插入的节点不是黑色,如果插入黑色的话,那一定会破坏“从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点”这个特性。
当插入的节点的父节点是红色的时候
叔叔节点为红色的时候调整的过程是:将新插入的节点作为起始点,然后将父亲节点和叔叔节点涂成黑色,将祖父节点涂成红色,然后以祖父节点为新的起始点再次进行同样的操作(如果新的起点的叔叔节点也为红色)。这样直到新的起始点为根节点为止,最后把根节点涂成黑色即可。
叔叔节点为黑色的时候调整的过程是:我们将以祖父节点为根的子树看成是RR型,然后进行RR型的调整(就是AVL树种的RR型),最后将新的根节点涂成黑色,将其两个孩子中不是红色的节点的颜色改成红色。
红黑树插入的几种情况
1.当插入的红黑树根节点是空,直接插入然后将当前节点变色成黑色。
2.当插入的节点的父节点是黑色,则直接直接插入。
3.如果插入的节点的父节点是红色,而且插入节点的叔叔节点也是红色,则将父节点和叔叔节点变成黑色,然后将祖父节点变成红色,再以祖父节点为起始节点来推理。
4.如果插入的节点父节点是红色,而且插入节点的叔叔节点是黑色,如果自己,父亲节点,祖父节点在一条线上,则对父亲节点进行左旋或者右旋操作。
5.如果插入的节点父节点是红色,而且插入节点的叔叔节点是黑色,如果自己,父亲节点,祖父节点不在一条线上,则先将这三个节点旋转成一条线,然后再进行左旋或者右旋操作。
5.红黑树的应用
java8中的HashMap,当HashMap中的存储的数据个数大于等于64,而且链表的长度大于等于8的时候,会将链表变成红黑树结构