实现一个完整功能的红黑树

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

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值