java语言实现红黑树
参照小码哥《恋上数据结构与算法》中实现的一颗红黑树
private static final boolean RED = false;
private static final boolean BLACK = true;
// 用户可自定义比较策略
private Comparator<E> comparator;
public RBTree() {
this(null);
}
public RBTree(Comparator<E> comparator) {
this.comparator = comparator;
}
private int size;
private Node<E> root;
private static class Node<E> {
E element;
Node<E> left;
Node<E> right;
Node<E> parent;
boolean color = RED;
public Node(E element, Node<E> parent) {
this.element = element;
this.parent = parent;
}
public boolean isLeaf() {
return left == null && right == null;
}
public boolean isLeftChild() {
return parent != null && this == parent.left;
}
public boolean isRightChild() {
return parent != null && this == parent.right;
}
public Node<E> sibling() {
if (isLeftChild()) return parent.right;
if (isRightChild()) return parent.left;
return null;
}
public boolean hasTwoChildren() {
return left != null && right != null;
}
@Override
public String toString() {
String str = "";
if (color == RED) {
str = "R_";
}
return str + element.toString();
}
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void clear() {
root = null;
size = 0;
}
public boolean contains(E element) {
return node(element) != null;
}
public void preOrder(Visitor<E> visitor) {
if (root == null || visitor == null) return;
preOrder(root, visitor);
}
private void preOrder(Node<E> node, Visitor<E> visitor) {
if (node == null || visitor.stop) return;
visitor.stop = visitor.visit(node.element);
preOrder(node.left, visitor);
preOrder(node.right, visitor);
}
public void inOrder(Visitor<E> visitor) {
if (root == null || visitor == null) return;
inOrder(root, visitor);
}
private void inOrder(Node<E> node, Visitor<E> visitor) {
if (node == null || visitor.stop) return;
inOrder(node.left, visitor);
if (visitor.stop) return;
visitor.stop = visitor.visit(node.element);
inOrder(node.right, visitor);
}
public void postOrder(Visitor<E> visitor) {
if (root == null || visitor == null) return;
postOrder(root, visitor);
}
private void postOrder(Node<E> node, Visitor<E> visitor) {
if (node == null || visitor.stop) return;
postOrder(node.left, visitor);
postOrder(node.right, visitor);
if (visitor.stop) return;
visitor.stop = visitor.visit(node.element);
}
public void levelOrder(Visitor<E> visitor) {
if (root == null || visitor == null) return;
Node<E> node = root;
Queue<Node<E>> queue = new LinkedList<>();
queue.offer(node);
while (!queue.isEmpty()) {
node = queue.poll();
// 保证传出的数据是对外可见的
if (visitor.visit(node.element)) return;
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
public int height() {
if (root == null) return 0;
int height = 0;
int levelSize = 1;
Node<E> node = root;
Queue<Node<E>> queue = new LinkedList<>();
queue.offer(node);
while (!queue.isEmpty()) {
node = queue.poll();
levelSize--;
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
if (levelSize == 0) { // 即将遍历下一层
height++;
levelSize = queue.size();
}
}
return height;
}
/**
* 是否为完全二叉树
*/
public boolean isComplete() {
if (root == null) return false;
Node<E> node = root;
Queue<Node<E>> queue = new LinkedList<>();
// 要求后面是否是叶子节点
boolean leaf = false;
queue.offer(node);
while (!queue.isEmpty()) {
node = queue.poll();
if (leaf && !node.isLeaf()) return false;
if (node.left != null) {
queue.offer(node.left);
} else if (node.right != null) {
return false;
}
if (node.right != null) {
queue.offer(node.right);
} else {
leaf = true;
}
}
return true;
}
/**
* 获得前驱节点
*/
public Node<E> predecessor(Node<E> node) {
if (node == null) return null;
// 前驱节点在左子树中
Node<E> p = node.left;
if (p != null) {
while (p.right != null) {
p = p.right;
}
return p;
}
// 前驱节点在父节点或祖先节点当中
while (node.parent != null && node != node.parent.left) {
node = node.parent;
}
return node.parent;
}
/**
* 后继节点
*/
public Node<E> successor(Node<E> node) {
if (node == null) return null;
// 后继节点在右子树中
Node<E> s = node.right;
if (s != null) {
while (s.left != null) {
s = s.left;
}
return s;
}
// 后继节点在父节点或祖先节点中
while (node.parent != null && node != node.parent.right) {
node = node.parent;
}
return node.parent;
}
public void add(E element) {
elementNotNullCheck(element);
// 添加第一个节点
if (root == null) {
root = new Node<>(element, null);
size++;
// 添加节点之后要进行的红黑树的平衡操作
afterAdd(root);
return;
}
Node<E> node = root;
// 为了记录新节点的父节点
Node<E> parent = root;
// 为了记录新节点将处于的位置
int cmp = 0;
while (node != null) {
cmp = compare(element, node.element);
parent = node;
if (cmp > 0) {
node = node.right;
} else if (cmp < 0) {
node = node.left;
} else { // 相等覆盖
node.element = element;
return;
}
}
Node<E> newNode = new Node<>(element, parent);
if (cmp > 0) {
parent.right = newNode;
} else {
parent.left = newNode;
}
size++;
// 添加节点之后要进行的红黑树的平衡操作
afterAdd(newNode);
}
private 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)) { // 叔父节点是红色,上溢
black(parent);
black(uncle);
// 将上溢的祖父节点当成新添加的节点
afterAdd(grand);
return;
}
// 叔父节点是黑色,不会上溢(在红黑树中null节点为黑色),进行旋转
if (parent.isLeftChild()) { // L
if (node.isLeftChild()) { // LL
black(parent);
} else { // LR
black(node);
rotateLeft(parent);
}
rotateRight(grand);
} else { // R
if (node.isLeftChild()) { // RL
black(node);
rotateRight(parent);
} else { // RR
black(parent);
}
rotateLeft(grand);
}
}
public void remove(E element) {
remove(node(element));
}
private void remove(Node<E> node) {
if (node == null) return;
size--;
if (node.hasTwoChildren()) { // 先处理叶子节点度为2的,使用叶子节点替换,转换为删除它的叶子节点
Node<E> s = successor(node); // 用后继节点替换
// 用后继节点的值覆盖度为1的节点的值
node.element = s.element;
node = s; // 将后驱节点删除,这个后驱节点的度为1或0
}
Node<E> replaceNode = node.left != null ? node.left : node.right;
if (replaceNode != null) { // 删除度为1的节点
replaceNode.parent = node.parent;
if (node.parent == null) { // node是root
root = replaceNode;
} else if (node == node.parent.left) {
replaceNode = node.parent.left;
} else {
replaceNode = node.parent.right;
}
// 红黑树调整
afterRemove(replaceNode);
} else if (node == root) { // 删除度为0并且是root
root = null;
} else { // 删除度为0的叶子节点
if (node == node.parent.left) {
node.parent.left = null;
} else {
node.parent.right = null;
}
// 红黑树调整
afterRemove(node);
}
}
private void afterRemove(Node<E> node) {
// 删除的节点是叶子节点是红色,或 用于取代node节点的replaceNode是红色,染黑
if (isRed(node)) {
black(node);
return;
}
Node<E> parent = node.parent;
if (parent == null) return; // 删除的节点是根节点
/* 删除的是黑色叶子节点 */
// 判断被删除的节点是左是右,左右处理方法对称
boolean left = parent.left == null || node.isLeftChild();
// 情况分为兄弟节点是否为黑色
Node<E> sibling = left ? parent.right : parent.left;
if (left) { // 被删除的节点在左边,兄弟节点在右边
if (isRed(sibling)) { // 兄弟节点是红色,将它转成黑色旋转然后在统一处理
black(sibling);
red(parent);
rotateLeft(parent);
// 旋转之后兄弟节点发生变化
sibling = parent.right;
}
// 兄弟节点必是黑色
if (isBlack(sibling.left) && isBlack(sibling.right)) { // 兄弟节点没有红色子节点,父节点要下溢,向下合并
// 如果父节点的颜色是黑色,父节点也会下溢
boolean parentBlock = isBlack(parent);
black(parent);
red(sibling);
if (parentBlock) { // 如果父节点之前同样也是黑色,那么此时会造成父节点【下溢】
afterRemove(parent);
}
} else { // 父节点中至少有一个红色节点,可借
if (isBlack(sibling.right)) { // 兄弟节点左子节点是黑色即为null,进行旋转后统一操作
rotateRight(sibling);
sibling = parent.right; // 旋转之后,删除节点的兄弟节点发生变化
}
color(sibling, colorOf(parent)); // 旋转之后的节点要继承中心节点的颜色
black(sibling.right); // 将旋转之后的叶子节点染成黑色
black(parent);
rotateLeft(parent);
}
} else { // 被删除的节点在右边,兄弟节点在左边
if (isRed(sibling)) { // 兄弟节点是红色,将它转成黑色旋转然后在统一处理
black(sibling);
red(parent);
rotateRight(parent);
// 旋转之后兄弟节点发生变化
sibling = parent.left;
}
// 兄弟节点必是黑色在这里插入图片描述
if (isBlack(sibling.left) && isBlack(sibling.right)) { // 兄弟节点没有红色子节点,父节点要下溢,向下合并
// 如果父节点的颜色是黑色,父节点也会下溢
boolean parentBlock = isBlack(parent);
black(parent);
red(sibling);
if (parentBlock) { // 如果父节点之前同样也是黑色,那么此时会造成父节点【下溢】
afterRemove(parent);
}
} else { // 父节点中至少有一个红色节点,可借
if (isBlack(sibling.left)) { // 兄弟节点左子节点是黑色即为null,进行旋转后统一操作
rotateLeft(sibling);
sibling = parent.left; // 旋转之后,删除节点的兄弟节点发生变化
}
color(sibling, colorOf(parent)); // 旋转之后的节点要继承中心节点的颜色
black(sibling.left); // 将旋转之后的叶子节点染成黑色
black(parent);
rotateRight(parent);
}
}
}
private Node<E> node(E element) {
Node<E> node = root;
while (node != null) {
int cmp = compare(element, node.element);
if (cmp > 0) {
node = node.right;
} else if (cmp < 0) {
node = node.left;
} else {
return node;
}
}
return null;
}
private void rotateLeft(Node<E> grand) {
Node<E> parent = grand.right;
Node<E> child = parent.left;
grand.right = child;
parent.left = grand;
// 维护旋转后的节点的parent
rotate(grand, parent, child);
}
private void rotateRight(Node<E> grand) {
Node<E> parent = grand.left;
Node<E> child = parent.right;
grand.left = child;
parent.right = grand;
rotate(grand, parent, child);
}
private void rotate(Node<E> grand, Node<E> parent, Node<E> child) {
// 让parent成为子树的根节点
parent.parent = grand.parent;
if (grand.isLeftChild()) {
grand.parent.left = parent;
} else if (grand.isRightChild()) {
grand.parent.right = parent;
} else { // grand是树的根节点
root = parent;
}
// 更新parent的父节点
if (child != null) {
child.parent = grand;
}
// 更新grand的parent
grand.parent = parent;
}
/**
* 根据传入的对象选择比较器
*/
private int compare(E e1, E e2) {
if (comparator != null) {
return comparator.compare(e1, e2);
}
return ((Comparable<E>) e1).compareTo(e2);
}
/**
* 用户获得相应节点之后可以自定义操作
*/
public static abstract class Visitor<E> {
// 为了记录什么时候结束
boolean stop;
/**
* 自定义,提供给用户调用几次,什么时候结束调用的接口
*
* @return 如果返回值为true,则停止遍历
*/
public abstract boolean visit(E element);
}
/**
* 不支持null
*/
private void elementNotNullCheck(E element) {
if (element == null) {
throw new IllegalArgumentException("element must be not null");
}
}
/**
* 上色
*/
private Node<E> color(Node<E> node, boolean color) {
if (node == null) return null;
node.color = color;
return node;
}
private Node<E> red(Node<E> node) {
return color(node, RED);
}
private Node<E> black(Node<E> node) {
return color(node, BLACK);
}
private boolean isRed(Node<E> node) {
return colorOf(node) == RED;
}
private boolean isBlack(Node<E> node) {
return colorOf(node) == BLACK;
}
/**
* 获取节点的颜色,如果是空节点null为BLACK
*
* @param node
* @return
*/
private boolean colorOf(Node<E> node) {
return node == null ? BLACK : node.color;
}
测试
add
static void test() {
RBTree<Integer> rbt = new RBTree<>();
Integer data[] = new Integer[]{
11, 2, 98, 96, 66, 43, 52, 21, 94, 37, 35, 82, 27, 88, 23
};
for (int i = 0; i < data.length; i++) {
rbt.add(data[i]);
}
BinaryTrees.println(rbt);
}
运行结果
┌────────52────────┐
│ │
┌─────27────┐ ┌─96─┐
│ │ │ │
┌─R_11─┐ ┌─R_37─┐ ┌─R_82─┐ 98
│ │ │ │ │ │
2 21─┐ 35 43 66 ┌─94
│ │
R_23 R_88
remove
rbt.remove(52);
┌────────66────────┐
│ │
┌─────27────┐ ┌─96─┐
│ │ │ │
┌─R_11─┐ ┌─R_37─┐ ┌─R_88─┐ 98
│ │ │ │ │ │
2 21─┐ 35 43 82 94
│
R_23
rbt.remove(88);
┌────────52────────┐
│ │
┌─────27────┐ ┌─96─┐
│ │ │ │
┌─R_11─┐ ┌─R_37─┐ ┌─R_82─┐ 98
│ │ │ │ │ │
2 21─┐ 35 43 66 94
│
R_23