【数据结构】java实现红黑树


红黑树五个性质(可以参考维基百科)

  1. 节点是红色或者黑色
  2. 根节点是黑色
  3. 叶子节点颜色为黑色(不是NULL节点,是自己构造的黑色叶子结点)
  4. 红色节点的孩子节点是黑色
  5. 从某个节点到其叶子结点的黑色节点个数相同

红黑树的插入和删除操作就是为了保证这五个性质,特别是性质4、5。因此,为了保证插入不破坏性质5,插入时节点颜色默认为红色


红黑树节点数据结构

package com.xll.tree.redblack;

/**
 * @Author: xialonglei469
 * @Date: 2019-9-24 14:38
 * @Version 1.0
 *
 * 红黑树节点数据结构
 */
public class Node {

    private int data;

    private Node lc;

    private Node rc;

    private Node parent;

    /** 红色 */
    public final static int RED = 1;

    /** 黑色 */
    public final static int BLACK = 2;

    /** 充当叶子节点,叶子节点不为NULL */
    public final static Node LEAF_NODE = new Node(BLACK);

    /** 节点颜色 */
    private int color = RED;

    public Node() {}

    public Node(int color) {
        this.color = color;
    }

    public Node(int data , Node parent) {
        this.data = data;
        this.parent = parent;
    }

    public Node(int data , int color , Node parent) {
        this.data = data;
        this.color = color;
        this.parent = parent;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public Node getLc() {
        return lc;
    }

    public void setLc(Node lc) {
        this.lc = lc;
    }

    public Node getRc() {
        return rc;
    }

    public void setRc(Node rc) {
        this.rc = rc;
    }

    public int getColor() {
        return color;
    }

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

    public Node getParent() {
        return parent;
    }

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

红黑树实现

package com.xll.tree.redblack;

/**
 * @Author: xialonglei469
 * @Date: 2019-9-24 14:44
 * @Version 1.0
 *
 * 红黑树
 */
public class RedBlackTree {

    /** 红黑书根节点,颜色为黑色 */
    private Node root;

    /**
     * 获取祖父节点
     */
    public Node grandparent(Node node) {

        return node.getParent().getParent();

    }

    /**
     * 获取兄弟节点
     */
    public Node sibling(Node node) {

        if (node == node.getParent().getLc()) {
            return node.getParent().getRc();
        } else {
            return node.getParent().getLc();
        }

    }

    /**
     * 获取叔父节点
     */
    public Node uncle(Node node) {

        if (node.getParent() == grandparent(node).getLc()) {

            return grandparent(node).getRc();

        } else {

            return grandparent(node).getLc();

        }

    }

    /**
     * 节点插入
     */
    public Node insert(int data) {

        Node node = executeInsert(data);

        insertAdjust0(node);

        return node;

    }

    /**
     * 节点删除
     */
    public Node delete(int data , Node node) {

        if (node == Node.LEAF_NODE) {
            return null;
        }

        int nodeData = node.getData();
        if (nodeData > data) {
            return delete(data , node.getLc());
        } else if (nodeData < data) {
            return delete(data , node.getRc());
        } else {

            if (node.getRc() == Node.LEAF_NODE) {

                deleteOneChild(node);

            } else {

                Node rcSmallestChild = getRcSmallestChild(node.getRc());
                node.setData(rcSmallestChild.getData());
                deleteOneChild(rcSmallestChild);
            }

        }

        return node;

    }

    private Node getRcSmallestChild(Node rc) {

        if (rc.getLc() == Node.LEAF_NODE) {
            return rc;
        }

        return getRcSmallestChild(rc.getLc());

    }

    private void deleteOneChild(Node node) {

        Node lc = node.getLc();
        Node rc = node.getRc();
        Node child = lc != Node.LEAF_NODE ? lc : rc;
        Node parent = node.getParent();

        if (parent == null &&
                lc == Node.LEAF_NODE &&
                rc == Node.LEAF_NODE) {

            root = null;
            return;

        }

        if (parent == null) {

            root = child;
            child.setColor(Node.BLACK);
            child.setParent(null);
            return;

        }

        if (parent.getLc() == node) {
            parent.setLc(child);
        } else {
            parent.setRc(child);
        }
        child.setParent(parent);

        // 如果删除节点为红色,则不做任何操作

        // 如果删除节点为黑色
        if (node.getColor() == Node.BLACK) {

            if (child.getColor() == Node.RED) {
                child.setColor(Node.BLACK);
            } else {
                deleteAdjust0(child);
            }

        }

    }

    private void deleteAdjust0(Node node) {

        if (node.getParent() == null) {
            return;
        }

        Node sibling = sibling(node);
        Node parent = node.getParent();

        if (sibling.getColor() == Node.RED) {

            parent.setColor(Node.RED);
            sibling.setColor(Node.BLACK);

            if (node == parent.getLc()) {
                rotateRight(parent);
            } else {
                rotateLeft(parent);
            }

        }

        deleteAdjust1(node);


    }

    private void deleteAdjust1(Node node) {

        Node sibling = sibling(node);

        if (node.getParent().getColor() == Node.BLACK &&
            sibling.getColor() == Node.BLACK &&
            sibling.getLc().getColor() == Node.BLACK &&
            sibling.getRc().getColor() == Node.BLACK) {

            sibling.setColor(Node.RED);

            deleteAdjust0(node.getParent());


        } else {

            deleteAdjust2(node);

        }

    }

    private void deleteAdjust2(Node node) {

        Node sibling = sibling(node);

        if (node.getParent().getColor() == Node.RED &&
            sibling.getColor() == Node.BLACK &&
            sibling.getLc().getColor() == Node.BLACK &&
            sibling.getRc().getColor() == Node.BLACK) {

            sibling.setColor(Node.RED);
            node.getParent().setColor(Node.BLACK);

        } else {

            deleteAdjust3(node);

        }



    }

    private void deleteAdjust3(Node node) {

        Node parent = node.getParent();
        Node sibling = sibling(node);
        Node sLc = sibling.getLc();
        Node sRc = sibling.getRc();
        if (sibling.getColor() == Node.BLACK) {
            if (parent.getLc() == node &&
                    sLc.getColor() == Node.RED &&
                    sRc.getColor() == Node.BLACK) {

                sLc.setColor(Node.BLACK);
                sibling.setColor(Node.RED);

                rotateRight(sibling);

            } else if (parent.getRc() == node &&
                    sLc.getColor() == Node.BLACK &&
                    sRc.getColor() == Node.RED) {

                sRc.setColor(Node.BLACK);
                sibling.setColor(Node.RED);
                rotateLeft(sibling);

            }
        }

        deleteAdjust4(node);

    }

    private void deleteAdjust4(Node node) {

        Node sibling = sibling(node);
        Node parent = node.getParent();
        sibling.setColor(parent.getColor());
        parent.setColor(Node.BLACK);

        if (node == parent.getLc()) {

            sibling.getRc().setColor(Node.BLACK);
            rotateLeft(parent);

        } else {

            sibling.getLc().setColor(Node.BLACK);
            rotateRight(parent);

        }

    }

    /**
     * 第一种情况,根节点插入,置为黑色即可
     */
    private void insertAdjust0(Node node) {

        if (node.getParent() == null) {
            node.setColor(Node.BLACK);
        } else {
            insertAdjust1(node);
        }

    }

    /**
     * 第二种情况,父节点为黑色,不用管
     */
    private void insertAdjust1(Node node) {

        if (node.getParent().getColor() == Node.BLACK) {
            return;
        } else {
            insertAdjust2(node);
        }

    }

    /**
     * 第三种情况,父节点为红色,叔父节点为红色
     */
    private void insertAdjust2(Node node) {

        Node parent = node.getParent();
        Node uncle = uncle(node);
        Node grandparent = grandparent(node);

        if (uncle != null && parent.getColor() == Node.RED &&
                uncle.getColor() == Node.RED) {

            parent.setColor(Node.BLACK);
            uncle.setColor(Node.BLACK);
            grandparent.setColor(Node.RED);

            insertAdjust0(grandparent);

        } else {

            insertAdjust3(node);

        }

    }

    /**
     * 第四种情况,父节点为红色,叔父节点为黑色或为空
     */
    private void insertAdjust3(Node node) {

        Node parent = node.getParent();
        Node grandparent = grandparent(node);

        // 父节点是祖父节点的左孩子,节点是父节点的右孩子
        if (node == parent.getRc() && parent == grandparent.getLc()) {

            rotateLeft(parent);
            node = node.getLc();

        }

        // 父节点是祖父节点的右孩子,节点是父节点的左孩子
        else if (node == parent.getLc() && parent == grandparent.getRc()) {

            rotateRight(parent);
            node = node.getRc();

        }

        insertAdjust4(node);

    }

    /**
     * 第五种情况,节点父亲为红色,叔父为黑色或为空
     */
    private void insertAdjust4(Node node) {

        Node parent = node.getParent();
        Node grandparent = grandparent(node);

        parent.setColor(Node.BLACK);
        grandparent.setColor(Node.RED);

        // 父节点是祖父节点的左孩子,节点是父节点的左孩子
        if (node == parent.getLc() && parent == grandparent.getLc()) {
            rotateRight(grandparent);
        }

        // 父节点是祖父节点的右孩子,节点是父节点的右孩子
        else {
            rotateLeft(grandparent);
        }

    }

    /**
     * 左旋
     */
    private void rotateLeft(Node node) {

        Node parent = node.getParent();
        Node rc = node.getRc();

        if (node == parent.getLc()) {
            parent.setLc(rc);
        } else {
            parent.setRc(rc);
        }
        rc.setParent(parent);

        Node rcLc = rc.getLc();
        node.setRc(rcLc);
        if (rcLc != Node.LEAF_NODE) {
            rcLc.setParent(node);
        }

        rc.setLc(node);
        node.setParent(rc);

    }

    /**
     * 右旋
     */
    private void rotateRight(Node node) {

        Node parent = node.getParent();
        Node lc = parent.getLc();

        if (node == parent.getLc()) {
            parent.setLc(lc);
        } else {
            parent.setRc(lc);
        }
        lc.setParent(parent);

        Node lcRc = lc.getRc();
        node.setLc(lcRc);
        if (lcRc != Node.LEAF_NODE) {
            lcRc.setParent(node);
        }

        lc.setRc(node);
        node.setParent(lc);

    }

    /**
     * 二叉搜索树插入方法
     */
    private Node executeInsert(int data) {


        if (root == null) {
            root = new Node(data , Node.BLACK , null);
            root.setLc(Node.LEAF_NODE);
            root.setRc(Node.LEAF_NODE);
            return root;
        }

        Node cur = root;

        return doInsert(data , cur);

    }

    private Node doInsert(int data, Node cur) {

        Node node = new Node(data , cur);
        if (data <= cur.getData()) {
            Node lc = cur.getLc();
            if (lc != Node.LEAF_NODE) {
                return doInsert(data , lc);
            } else {
                cur.setLc(node);
                node.setLc(Node.LEAF_NODE);
                node.setRc(Node.LEAF_NODE);
            }
        } else {
            Node rc = cur.getRc();
            if (rc != Node.LEAF_NODE) {
                return doInsert(data , rc);
            } else {
                cur.setRc(node);
                node.setLc(Node.LEAF_NODE);
                node.setRc(Node.LEAF_NODE);
            }
        }

        return node;

    }

    public static void main(String[] args) {

        RedBlackTree redBlackTree = new RedBlackTree();

        redBlackTree.insert(13);
        redBlackTree.insert(8);
        redBlackTree.insert(17);
        redBlackTree.insert(1);
        redBlackTree.insert(11);
        redBlackTree.insert(15);
        redBlackTree.insert(25);
        redBlackTree.insert(6);
        redBlackTree.insert(22);
        redBlackTree.insert(27);
        
        redBlackTree.delete(13 , redBlackTree.root);

        System.out.println();

    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章