红黑树(Java实现)

RBTree

  1. 根节点是黑色
  2. 每个叶子节点都是黑色的空结点(NIL结点)(为了简单期间,一般会省略该节点)
  3. 如果一个节点是红色的,则它的子节点必须是黑色的(父子不能同为红)
  4. 从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点(平衡的关键)
  5. 新插入节点默认为红色,插入后需要校验红黑树是否符合规则,不符合则需要进行平衡

节点

package com.richard.brtree;

public class BRTreeNode {

    private int key;
    private boolean isBlack;
    private BRTreeNode left;
    private BRTreeNode right;
    private BRTreeNode parent;

    public BRTreeNode(int key) {
        this.key = key;
        this.isBlack = false; // 新节点默认是红
    }

    @Override
    public String toString() {
        return "BRTreeNode{" +
                "key=" + key +
                ", color=" + (isBlack==true?"BLACK":"RED")+
                '}';
    }

    public int getKey() {
        return key;
    }

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

    public boolean isBlack() {
        return isBlack;
    }

    public void setBlack(boolean black) {
        isBlack = black;
    }

    public BRTreeNode getLeft() {
        return left;
    }

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

    public BRTreeNode getRight() {
        return right;
    }

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

    public BRTreeNode getParent() {
        return parent;
    }

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

实现

package com.richard.brtree;


import com.sun.media.sound.FFT;
import com.sun.xml.internal.bind.v2.model.core.ID;

/**
 * 红黑树
 */
public class RBTree {

    // 根节点
    BRTreeNode root;

    /**
     * 遍历节点
     * @param node
     */
    public void list(BRTreeNode node) {
        if (node == null) {
            return ;
        }

        // 到叶子了  递归终止条件
        if (node.getLeft() == null && node.getRight() == null) {
            System.out.println(node);
            return ;
        }

        // 遍历节点
        System.out.println(node);
        list(node.getLeft());
        list(node.getRight());
    }

    /**
     * 插入节点
     * @param key
     */
    public void insert(int key) {
        BRTreeNode node = new BRTreeNode(key);

        // 插入根节点
        if (root == null) {
            node.setBlack(true); // 根是黑的
            root = node;
            return ;
        }

        BRTreeNode parent = root;
        BRTreeNode son = null;

        // 左孩子
        if (key <= parent.getKey()) {
            son = parent.getLeft();
        } else { // 右孩子
            son = parent.getRight();
        }

        // 递归查找
        while (son != null) {
            parent = son;
            if (key <= parent.getKey()) {
                son = parent.getLeft();
            } else {
                son = parent.getRight();
            }
        }

        // 开始添加
        if (key <= parent.getKey()) {
            // 添加左孩子
            parent.setLeft(node);
        } else {
            // 添加右孩子
            parent.setRight(node);
        }
        node.setParent(parent);
        balanceInsert(node);
    }

    /**
     * 插入自平衡
     *  左旋右旋颜色反转
     * @param node
     */
    private void balanceInsert(BRTreeNode node) {

        BRTreeNode father, gFather;
        // 父节点是红的
        while ((father=node.getParent()) != null && father.isBlack() == false) {
            gFather = father.getParent();
            // 父节点在祖父节点的左面
            if (gFather.getLeft() == father) {
                BRTreeNode uncle = gFather.getRight();
                if (uncle != null && uncle.isBlack() == false) {
                    // 颜色反转
                   setBlack(father);
                   setBlack(uncle);
                   setRed(gFather);
                   node = gFather;
                   continue;
                }
                if (node == father.getRight()) {
                    // 进行左旋
                    leftRotate(father);
                    // 交换
                    BRTreeNode tmp = node;
                    node = father;
                    father = tmp;
                }
                setBlack(father);
                setRed(gFather);
                // 右旋
                rightRotate(gFather);
            } else {// 父节点在祖父节点的右面
                BRTreeNode uncle = gFather.getLeft();
                if (uncle != null && uncle.isBlack() == false) {
                    // 颜色反转
                    setBlack(father);
                    setBlack(uncle);
                    setRed(gFather);
                    node = gFather;
                    continue;
                }
                if (node == father.getLeft()) {
                    // 进行右旋旋
                    rightRotate(father);
                    // 交换
                    BRTreeNode tmp = node;
                    node = father;
                    father = tmp;
                }
                setBlack(father);
                setRed(gFather);
                // 左旋
                leftRotate(gFather);
            }
        }
        setBlack(root);
    }

    /**
     * 左旋
     * @param node
     */
    private void leftRotate(BRTreeNode node) {

        BRTreeNode right = node.getRight();
        BRTreeNode parent = node.getParent();

        // 父节点没有 root
        if (parent == null) {
            root = right;
            right.setParent(null);
        } else {
            if (parent.getLeft() != null && parent.getLeft() == node) {
                parent.setLeft(right);
            }else {
                parent.setRight(right);
            }
            right.setParent(parent);
        }
        node.setParent(right);
        node.setRight(right.getLeft());
        if (right.getLeft() != null) {
            right.getLeft().setParent(node);
        }
        right.setLeft(node);


    }

    /**
     * 右旋
     * @param node
     */
    private void rightRotate(BRTreeNode node) {
        BRTreeNode left = node.getLeft();
        BRTreeNode parent = node.getParent();
        if (parent == null) {
            root = left;
            left.setParent(null);
        } else {
            if (parent.getLeft() != null && parent.getLeft() == node) {
                parent.setLeft(left);
            } else {
                parent.setRight(left);
            }
                left.setParent(parent);
        }
            node.setParent(left);
        node.setLeft(left.getRight());
        if (left.getRight() != null) {
            left.getRight().setParent(node);
        }
            left.setRight(node);
    }

    /**
     * 设置黑色
     * @param node
     */
    private void setBlack(BRTreeNode node) {
        node.setBlack(true);
    }

    /**
     * 设置红色
     * @param node
     */
    private void setRed(BRTreeNode node) {
        node.setBlack(false);
    }

    public static void main(String[] args) {
        RBTree rbTree = new RBTree();
        rbTree.insert(10); // 根节点
        rbTree.insert(5);
        rbTree.insert(9);
        rbTree.insert(3);
        rbTree.insert(6);
        rbTree.insert(7);
        rbTree.insert(19);
        rbTree.insert(32);
        rbTree.insert(24);

        rbTree.list(rbTree.root);
    }
}


运行截图
在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值