红黑树
1.概述
红黑树解决了二叉查找树多次插入新节点可能导致的不平衡问题,红黑树是一种自平衡的二叉查找树,除了符合二叉查找树的基本特性外,它还具有以下特性:
1.节点是红色或者黑色。
2.根节点是黑色。
3.每个叶子节点都是黑色的空节点(NIL节点)。
4.每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上都不能有两个连续的红色节点)。
5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
具体结构如图:
学习红黑树的概念,需要先了解什么是二叉查找树。
2.二叉查找树
二叉查找树(BST)的特性:
1.左子树上所有节点的数值均小于或等于它根节点的值
2.右子树上所有节点的数值均大于或等于它根节点的值
3.左,右子树也分别为二叉查找树
二叉查找树的结构如图:
举例说明
如果我们要查询值为10的节点用二叉查找树会怎么来查呢?
1.首先查看根节点9
2.由于10>9,因此查看右子树节点13
3.由于10<13,因此查看13节点下左子树的11
4由于10<11,因此查看11节点下左子树的10,发现10正是要查找的节点
由上我们可以得出查找所需的最大次数等同于二叉查找树的高度。
插入节点
在插入节点的适合也是利用类似的方法,通过一层层比较大小,找到新节点适合插入的位置。
缺点
缺点体现在多次插入新节点时二叉查找树有可能会出现不平衡,这样大大降低查找的效率
例如:
假设初始的二叉查找树只有三个节点,根节点值为9,左子树值为8,右子树值为12
接下来我们依次插入五个节点: 7,6,5,4,3,依照二叉查找树的特性,结果几乎变成了线性。
总结
正是二叉查找树的这个缺陷,多次插入新节点有可能导致数据结构的不平衡,而产生了红黑树这种更高效合理的数据结构。
3.红黑树
从文章开始的地方我们可以知道红黑树的特点,正是因为在二叉查找树的基础上增加的这些新的特点和规则,才保证了红黑树的自平衡,红黑树从根到叶子的最长路径不会超过最短路径的两倍。
当插入或删除节点的时候,红黑叔的规则有可能被打破。
举例说明
一.不会破坏红黑树规则的情况
1.向原红黑树插入值为14的新节点
由于父节点15是黑色节点,因此这种情况并不会破坏红黑树的规则,无需做任何调整
二.会破坏红黑树规则的情况
1.向原红黑树插入值为21的新节点:
由于父节点22是红色节点,因此破坏了红黑树的规则4(从每个叶子到根的所有路径上都不能有两个连续的红色节点),必须调整使之符合红黑树的规则
调整方法
1.变色
为了符合红黑树的规则,尝试把红色节点变成黑色,或者把黑色节点变成红色。
下图所表示的是红黑树的一部分,需要注意节点25并不是根节点,因为节点21和节点22连续出现了红色,不符合规则4,所以把节点22从红色变成黑色
因为右多出的黑色节点打破了规则5(从任一节点到其叶子的路径上都包含数量相同的黑色节点)所以发生连锁反应,需要继续把节点25从黑色变成红色。
此时因为出现了两个连续红色节点打破了规则6(从根节点到叶子的路径上不能出现两个连续的红色节点),需要继续把节点27从红色变成黑色。
如上完成了所有的变色调整后才算是一次完整的红黑树的自平衡。
2.旋转
红黑树的旋转调整又分为左旋转和右旋转
我们来先看左旋转:
逆时针旋转红黑树的两个节点,使得父节点被自己的右子树取代,而自己成为自己的左子树。
如图:
身为右子树的Y取代了X的位置,而X变成了自己的左子树。此为左旋转。
关于右旋转:
顺时针旋转红黑树的两个节点,使得父节点被自己的左子树取代,而自己成为自己的右子树。
如图:
身为左子树的Y取代了X的位置,而X变成了自己的右子树,此为右旋转。
4.红黑树的应用
红黑树的应用有很多,其中JDK的集合类TreeMap和TreeSet底层都是用的红黑树实现,在Java8中HashMap也使用了红黑树。