【數據結構】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();

    }

}

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