文章目录
- 代码框架
- 添加(12种情况)
- 修复性质4(添加在父节点为红色的情况)
- LL(RR)两种
- LR(RL)两种
- 上溢(四种)Uncle是红色
- 添加代码
- 删除
- 删除——red节点
- 删除——black节点(3情况)
- 删除——拥有一个red节点的black节点
- 删除——black叶子节点,sibling为black(方法是借兄弟)
- 删除——black叶子节点,sibling为black(兄弟借不了,父节点下来合并)
- 删除——black叶子节点,sibling为red(借兄弟的孩子)
- 删除代码
代码框架
import java.util.Comparator;
public class RBTree<E> extends BinarySearchTree<E>{
private static final boolean RED = false;
private static final boolean BLACK = true;
public RBTree() {
this(null);
}
public RBTree(Comparator<E> comparator) {
super(comparator);
}
/**
* 红黑树的节点类
* 节点有颜色,RED 或者 BLACK
*默认新添加为红色
*/
private static class RBNode<E> extends Node<E> {
boolean color = RED;
public RBNode(E element, Node<E> parent) {
super(element, parent);
}
@Override
public String toString() {
String str = "";
if (color == RED) {
str = "R_";
}
return str + element.toString();
}
}
@Override
protected void afterAdd(Node<E> node) {
}
@Override
protected void afterRemove(Node<E> node) {
}
}
添加(12种情况)
添加的所有情况
17左右,33左右,46左,50左右,72左右,76右,88左右,一共12种
在黑节点后+节点,满足红黑树的性质;而在红色叶子节点后+节点,不满足红黑树性质
以下是修复的方法
修复性质4(添加在父节点为红色的情况)
LL(RR)两种
在祖父节点的右孩子的右边添加或在祖父节点的左孩子的左边添加。
若新添加的元素的叔父节点不是红色的情况
LR(RL)两种
上溢(四种)Uncle是红色
粉红色为新增加的节点
(LL)
(RR)
(LR)
(RL)
添加代码
@Override
protected void afterAdd(Node<E> node) {
Node<E> parent = node.parent;
// 添加的是根节点 或者 上溢到达了根节点
if (parent == null) {
black(node);//把根节点变黑
return;
}
// 如果父节点是黑色,直接返回
if (isBlack(parent)) return;
// 叔父节点
Node<E> uncle = parent.sibling();
// 祖父节点
Node<E> grand = red(parent.parent);
if (isRed(uncle)) { // 叔父节点是红色【B树节点上溢】
black(parent);
black(uncle);
// 把祖父节点当做是新添加的节点
afterAdd(red(grand));
return;
}
// 叔父节点不是红色
if (parent.isLeftChild()) { // L
if (node.isLeftChild()) { // LL
black(parent);
red(grand);
rotateRight(grand);
} else { // LR
black(node);
red(grand);
rotateLeft(parent);
rotateRight(grand);
}
rotateRight(grand);
} else { // R
if (node.isLeftChild()) { // RL
black(node);
red(grand);
rotateRight(parent);
rotateLeft(grand);
} else { // RR
black(parent);
red(grand);
rotateLeft(grand);
}
}
}
删除
删除——red节点
删除——black节点(3情况)
删除——拥有一个red节点的black节点
应该通过节点颜色判断,而不是用二叉搜索树里度为几的概念来判断
删除——black叶子节点,sibling为black(方法是借兄弟)
B树要求父节点的元素个数比它子节点的个数少1,如图,要删除88,就会出现下溢的情况
76是88的兄弟
第三个选择了LL,只旋转一次,如果LR的需要旋转两次
删除——black叶子节点,sibling为black(兄弟借不了,父节点下来合并)
如果删除节点的父节点为红,那么她边上定有合并的黑色节点,它下来合并,原来的节点就不会发生下溢。
如果删除节点的父节点为黑,下来的话上面就会发生下溢
不肯能存在父节点为黑,她边上定有合并的红色节点,因为条件就是被删除元素的兄弟节点为黑
删除——black叶子节点,sibling为red(借兄弟的孩子)
将兄弟孩子变成兄弟,这样就可以套用上面的方法(当兄弟是黑色节点时就借兄弟)
让80右旋转
删除代码