二叉排序树有一个问题:
比如:假设初始的二叉查找树只有三个节点,根节点值为9,左孩子值为8,右孩子值为12:
接下来我们依次插入如下五个节点:7,6,5,4,3,于是二叉排序树变为:
显然,根本不能发挥出二叉排序树二分查找的优势,几乎就是线性的时间复杂度
如何解决二叉排序树因为多次插入新节点而导致的不平衡?----红黑
红黑树的定义:
1.树的每一个结点有黑色和红色两种颜色
2.根节点是黑色的,叶子结点都是空结点,都是黑色的
3.如果一个结点是红色的,那么它的子节点必须是黑色的(只说了父红子必须黑,当父亲是黑色时候,孩子可以是红的也可以是黑的)
4.任何一个结点到它的所有叶子结点的路径中,黑色结点数目都是一样的
有了这些规则限制保证了红黑树的自平衡(从根到叶子节点的最长路径不会超过最短路径的两倍)
比如上面图里面的17一共有六条路径到叶子结点,每条路径上的黑色结点数目都是2
红黑树的左旋:
根据某个结点左旋,就是这个结点的右子树结点变成这个结点的父节点,这个结点变成原来右孩子节点的左孩子结点
红黑树的右旋:
根据某个结点右旋,就是将这个结点的左子树结点变成这个结点的父节点,这个结点变成原来左孩子结点的右结点
红黑树的添加:
①将红黑树看作一颗二叉查找树,并以二叉树的插入规则插入新节点;
②将插入的节点涂为“红色”或“黑色”;
③通过左旋、右旋或着色操作,使之重新成为一颗红黑树。
红黑树的删除:
①将红黑树看作一颗二叉查找树,根据二叉查找树的删除规则删除节点;
②通过左旋、旋转、重新着色操作进行树修正,使之重新成为一棵红黑树
向这棵红黑树中添加值为14的新结点:
由于父节点15是黑色节点,没有破坏红黑树的规则,无需调整
但如果添加值为21的新结点:
由于父节点22是红色节点,打破了红黑树的规则:每个红色节点的两个子节点都是黑色,所以必须进行调整,使之重新符合红黑树的规则。
变色(尝试把红色节点变为黑色,或者把黑色节点变为红色)和旋转(包括左旋转和右旋转)
要经过变色 -> 左旋转 -> 变色 -> 右旋转 -> 变色才能调整好
TreeMap和TreeSet底层就是红黑树实现的,Java8中,HashMap中也用到了红黑树