每日学习:红黑树java实现

本文介绍了一个红黑树的Java实现,包括插入操作及其平衡调整过程。通过左旋、右旋等方法确保树的性质得以维持。
package com.song.rbtree;

public class RBTree<K extends Comparable<K>,V> {
    private static final boolean RED=true;
    private static final boolean BLACK = false;

    /**树根的引用*/
    private RBNode root;

    static class RBNode<K extends Comparable<K>,V>{
        private RBNode parent;
        private RBNode left;
        private RBNode right;
        private boolean color;
        private K key;
        private V value;

        public RBNode(RBNode parent, RBNode left, RBNode right, boolean color, K key, V value) {
            this.parent = parent;
            this.left = left;
            this.right = right;
            this.color = color;
            this.key = key;
            this.value = value;
        }

        public RBNode() {
        }

        public RBNode getParent() {
            return parent;
        }

        public void setParent(RBNode parent) {
            this.parent = parent;
        }

        public RBNode getLeft() {
            return left;
        }

        public void setLeft(RBNode left) {
            this.left = left;
        }

        public RBNode getRight() {
            return right;
        }

        public void setRight(RBNode right) {
            this.right = right;
        }

        public boolean isColor() {
            return color;
        }

        public void setColor(boolean color) {
            this.color = color;
        }

        public K getKey() {
            return key;
        }

        public void setKey(K key) {
            this.key = key;
        }

        public V getValue() {
            return value;
        }

        public void setValue(V value) {
            this.value = value;
        }
    }

    /**
     * 节点是否为红色
     * @param node
     */
    private boolean isRed(RBNode node){
        if (node!=null){
            return node.color==RED;
        }
        return false;
    }
    /**
     *获取当前节点的父节点
     * @param  node
     */
    private RBNode parentOf(RBNode node){
        if(node!=null){
            return node.parent;
        }
        return null;
    }

    /**
     * 节点是否为黑色
     * @param node
     */
    private boolean isBlack(RBNode node){
        if (node!=null){
            return node.color==BLACK;
        }
        return false;
    }
    /**
     * 设置节点颜色为红色
     * @param node
     */
    private void setRed(RBNode node){
        if (node!=null){
            node.color=RED;
        }
    }
    /**
     * 设置节点颜色为黑色
     * @param node
     */
    private void setBlack(RBNode node){
        if (node!=null){
            node.color=BLACK;
        }
    }
    /**
     * 中序打印红黑树
     */
    public void inOrderPrint(){
        inOrderPrint(this.root);
        System.out.println();
    }
    private void inOrderPrint(RBNode node){
        if (node!=null){
            inOrderPrint(node.left);
            System.out.print(" "+node.key);
            inOrderPrint(node.right);
        }
    }
    /**
     * 左旋方法
     * 1 将y的左节点的父节点变为x   并将x的右节点指向y的左子节点
     * 2 将x的父节点(不为空)  更新为y的父节点  将 x的父节点的子树节点指定为y
     * 3 将x的父节点更新为y  y的左子节点指向x
     */
    private void leftRotate(RBNode x){
        RBNode y=x.right;
        x.right=y.left;
        if (y.left!=null){
            y.left.parent=x;
        }
        if (x.parent!=null){
            y.parent=x.parent;
            if (x.parent.left==x){
                x.parent.left=y;
            }else {
                x.parent.right=y;
            }
        }else {
            this.root=y;
            this.root.parent=null;
        }
        x.parent=y;
        y.left=x;
    }
    /**
     * 右旋方法
     * 1 将x的右节点的父节点更新为y 将y的左节点指向x的右节点
     * 2 将x父节点更新为y的父节点  更新y的父节点的 子树节点指向x
     * 3 将y的父节点更新为x   x的右节点指向y
     */
    private void rightRotate(RBNode y){
        RBNode x=y.left;
        y.left=x.right;
        if (x.right!=null){
            x.right.parent=y;
        }
        if (y.parent!=null){
            x.parent=y.parent;
            if (y.parent.left==y){
                y.parent.left=x;
            }else {
                y.parent.right=x;
            }
        }else {
            this.root=x;
            this.root.parent=null;
        }
        y.parent=x;
        x.right=y;
    }
    /**
     * 插入数据额
     * @param key
     * @param value
     */
    public void insert(K key,V value){
        RBNode<K, V> node = new RBNode<K, V>();
        node.setKey(key);
        node.setValue(value);
        node.setColor(RED);
        insert(node);
    }
    private void insert(RBNode node){
        RBNode parent=null;
        RBNode x=this.root;
        while (x!=null){
            parent=x;
            int cmp = node.key.compareTo(x.key);
            if (cmp>0){
                x=x.right;
            }else if (cmp==0){
                x.setValue(node.getValue());
                return;
            }else {
                x=x.left;
            }
        }
        node.parent=parent;
        if (parent!=null){
            int cmp = node.key.compareTo(parent.key);
            if (cmp>0){
                parent.right=node;
            }else {
                parent.left=node;
            }
        }else {
            this.root=node;
        }
        //修复红黑树平衡的方法
        insertFixup(node);

    }

    /**
     * 1 插入节点的父节点为黑色
     * 2 插入加点key已存在
     * 3 空树
     * 以上三点不需要变化
     * 插入节点的父节点为红色
     *      叔叔节点为红色   父亲  叔叔节点变黑色  爷爷加点为红色  然后爷爷节点为当前节点
     *      叔叔节点为黑色 或nil
     *          LL时    父节点变黑色  爷爷节点变红色  爷爷节点右旋
     *          LR时    父亲节点左旋  变为LL处理
     *          RR时     父亲节点变黑色  爷爷节点变红色  爷爷节点左旋
     *          RL时     父亲节点右旋  变为RR处理
     *
     */
     private void insertFixup(RBNode node) {
         this.root.setColor(BLACK);
         RBNode parent = parentOf(node);
         RBNode gparent = parentOf(parent);
         if (parent != null && isRed(parent)) {
             //父节点为红色  一定存在爷爷节点
             RBNode uncle = null;
             if (parent == gparent.left) {
                 uncle = gparent.right;
                 if (uncle != null && isRed(uncle)) {
                     parent.setColor(BLACK);
                     uncle.setColor(BLACK);
                     gparent.setColor(RED);
                     insertFixup(gparent);
                     return;
                 }
                 //叔叔节点不存在或者为黑色
                 if (uncle == null || isBlack(uncle)) {
                     if (node == parent.left) {
                         parent.setColor(BLACK);
                         gparent.setColor(RED);
                         rightRotate(gparent);
                         return;
                     } else {
                         leftRotate(parent);
                         insertFixup(parent);
                         return;
                     }
                 }
             } else {
                 uncle = gparent.left;
                 if (uncle != null && isRed(uncle)) {
                     parent.setColor(BLACK);
                     uncle.setColor(BLACK);
                     gparent.setColor(RED);
                     insertFixup(gparent);
                     return;
                 }
                 if (uncle == null || isBlack(uncle)) {
                     if (node == parent.right) {
                         parent.setColor(BLACK);
                         gparent.setColor(RED);
                         leftRotate(gparent);
                         return;
                     } else {
                         rightRotate(parent);
                         insertFixup(parent);
                         return;
                     }
                 }
             }
         }
     }
}















评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值