溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

java實現(xiàn)紅黑樹的代碼怎么寫

發(fā)布時間:2022-03-02 11:04:31 來源:億速云 閱讀:156 作者:iii 欄目:web開發(fā)

本篇內(nèi)容介紹了“java實現(xiàn)紅黑樹的代碼怎么寫”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

紅黑樹java代碼實現(xiàn)

package tree;

import jdk.nashorn.internal.ir.CallNode;

import java.util.Random;

/**
 * 紅黑樹
 * 思想源于:https://www.cnblogs.com/nananana/p/10434549.html
 */
public class RBTree {
    private RBTree.Node root = null;

    private enum Color {RED, BLACK}

    private enum Child {LEFT, RIGHT}

    private class Node {
        private Integer key;    //key
        private Object data;    //value
        private Node leftChild;   //左子節(jié)點
        private Node rightChild;  //右子節(jié)點
        private Node parent;  //父節(jié)點
        private Color color;   //紅黑標(biāo)示

        private Node() {
        }

        Node(Object key, Object data, Color color) {
            this.key = (Integer) key;
            this.data = data;
            this.color = color;
        }

        public Color getColor() {
            return color;
        }

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

        boolean isRed() {
            if (this.color.equals(Color.RED))
                return true;
            return false;
        }
    }

    /**
     * 插入數(shù)據(jù)
     *
     * @param value 插入數(shù)據(jù)
     * @return 數(shù)據(jù)重復(fù)返回false
     */
    boolean insertNode(Integer key, Object value) {
        return insertNode(root, key, value, null, Child.LEFT);
    }

    private boolean insertNode(Node node, Integer key, Object value, Node preNode, Child child) {
        if (node == null) {
            node = new Node(key, value, Color.RED);
            if (preNode == null) {  //父節(jié)點為空,將node設(shè)為根節(jié)點
                root = node;
            } else {
                if (child.equals(Child.LEFT)) {
                    preNode.leftChild = node;
                } else {
                    preNode.rightChild = node;
                }
                node.parent = preNode;
            }

            //通過RB_INSERT_FIXUP對紅黑樹的結(jié)點進(jìn)行顏色修改以及旋轉(zhuǎn),讓樹仍然是一顆紅黑樹
            RB_INSERT_FIXUP(node);
            return true;
        } else {
            if (key.compareTo(node.key) == 0) {
                //root = node;
                return false;
            } else if (key.compareTo(node.key) < 0) {
                if (!insertNode(node.leftChild, key, value, node, Child.LEFT)) {
                    return false;
                }
            } else {
                if (!insertNode(node.rightChild, key, value, node, Child.RIGHT)) {
                    return false;
                }
            }
            return true;
        }
    }

    /**
     * @param node 插入節(jié)點
     */
    private void RB_INSERT_FIXUP(Node node) {
        Node pNode = node.parent;
        if (node == root) { //插入結(jié)點為跟節(jié)點,直接改變顏色
            node.setColor(Color.BLACK);
            return;
        }
        if (node == null || pNode.color.equals(Color.BLACK)) {    //插入結(jié)點的父結(jié)點為黑結(jié)點,由于插入的結(jié)點是紅色的,并不會影響紅黑樹的平衡,直接插入即可,無需做自平衡。
            return;
        } else {    //情景4:插入結(jié)點的父結(jié)點為紅結(jié)點
            Node graNode = node.parent.parent;
            if (pNode == graNode.leftChild) {  //父節(jié)點是祖父節(jié)點的左子節(jié)點
                if (graNode.rightChild != null && graNode.rightChild.isRed()) { //情景4.1:叔叔結(jié)點存在并且為紅結(jié)點
                    /*將P和S設(shè)置為黑色(當(dāng)前插入結(jié)點I)將gra設(shè)置為紅色 把gra設(shè)置為當(dāng)前插入結(jié)點*/
                    pNode.setColor(Color.BLACK);
                    graNode.rightChild.setColor(Color.BLACK);
                    graNode.setColor(Color.RED);
                    RB_INSERT_FIXUP(graNode);
                } else { //情景4.2:叔叔結(jié)點不存在或為黑結(jié)點,并且插入結(jié)點的父親結(jié)點是祖父結(jié)點的左子結(jié)點
                    if (node == pNode.leftChild) {//情景4.2.1 插入結(jié)點是其父結(jié)點的左子結(jié)點
                        /*將P設(shè)為黑色 將gra設(shè)為紅色 對gra進(jìn)行右旋*/
                        pNode.setColor(Color.BLACK);
                        graNode.setColor(Color.RED);
                        RRotate(graNode);
                    } else {    //情景4.2.2 插入結(jié)點是其父結(jié)點的右子結(jié)點
                        /*對P進(jìn)行左旋 把P設(shè)置為插入結(jié)點,得到情景4.2.1 進(jìn)行情景4.2.1的處理*/
                        LRotate(pNode);
                        RB_INSERT_FIXUP(pNode);
                    }

                }
            } else { //4.3 父節(jié)點是祖父節(jié)點的右子節(jié)點
                if (graNode.leftChild != null && graNode.leftChild.isRed()) { //情景4.3:叔叔結(jié)點存在并且為紅結(jié)點+
                    /*將P和S設(shè)置為黑色(當(dāng)前插入結(jié)點I)將gra設(shè)置為紅色 把gra設(shè)置為當(dāng)前插入結(jié)點*/
                    pNode.setColor(Color.BLACK);
                    graNode.leftChild.setColor(Color.BLACK);
                    graNode.setColor(Color.RED);
                    RB_INSERT_FIXUP(graNode);
                } else { //情景4.3.1:叔叔結(jié)點不存在或為黑結(jié)點,并且插入結(jié)點的父親結(jié)點是祖父結(jié)點的左子結(jié)點
                    if (node == pNode.rightChild) {//情景4.3.1:插入結(jié)點是其父結(jié)點的右子結(jié)點
                        /*將P設(shè)為黑色 將gra設(shè)為紅色 對PP進(jìn)行左旋*/
                        pNode.setColor(Color.BLACK);
                        graNode.setColor(Color.RED);
                        LRotate(graNode);
                    } else {    //情景4.3.2 插入結(jié)點是其父結(jié)點的右子結(jié)點
                        /*對P進(jìn)行右旋 把P設(shè)置為插入結(jié)點,得到情景4.3.1 進(jìn)行情景4.3.1的處理*/
                        RRotate(pNode);
                        RB_INSERT_FIXUP(pNode);
                    }
                }
            }
        }
    }

    /**
     * 右旋
     *
     * @param T
     */
    private void RRotate(Node T) {
        Node lc = T.leftChild;
        T.leftChild = lc.rightChild;
        if (T.leftChild != null) {
            T.leftChild.parent = T;
        }
        lc.rightChild = T;
        returnPNode(T, lc);
    }

    private Node returnPNode(Node T, Node node) {
        if (T == root) {
            root = node;
        } else if (T.parent.leftChild == T) {
            T.parent.leftChild = node;
        } else {
            T.parent.rightChild = node;
        }
        node.parent = T.parent;
        T.parent = node;
        return node;
    }

    /**
     * 左旋
     *
     * @param T
     */
    private void LRotate(Node T) {
        Node rc = T.rightChild;
        T.rightChild = rc.leftChild;
        if (T.rightChild != null) {

            T.rightChild.parent = T;
        }
        rc.leftChild = T;
        returnPNode(T, rc);
    }

    /**
     * 中序
     */
    public void ldrTraversal() {
        ldrTraversal(root);
    }

    /**
     * 中序
     */
    private void ldrTraversal(Node node) {
        if (node != null) {
            ldrTraversal(node.leftChild);
            System.out.print(node.key + ":" + node.color + ";");
            //System.out.print("key:" + node.key + "-value" + node.data + ":" + node.color + ";");
            ldrTraversal(node.rightChild);
        }

    }

    /**
     * 先序
     */
    public void dlrTraversal() {
        dlrTraversal(root);
    }

    /**
     * 先序
     */
    private void dlrTraversal(Node node) {
        if (node != null) {
            System.out.print(node.key + ":" + node.color + ";");
            dlrTraversal(node.leftChild);
            dlrTraversal(node.rightChild);
        }

    }

    /**
     * 后序
     */
    public void lrdTraversal() {
        lrdTraversal(root);
    }

    /**
     * 后序
     */
    private void lrdTraversal(Node node) {
        if (node != null) {
            lrdTraversal(node.leftChild);
            lrdTraversal(node.rightChild);
            System.out.print("key:" + node.key + "-value" + node.data + ":" + node.color + ";");
        }

    }

    /**
     * 搜索
     *
     * @param key 傳入key
     * @return 返回value
     */
    public Object search(Integer key) {
        if (this.root != null) {
            return searchNode(key, root).data;
        }
        return null;
    }

    /**
     * @param key 刪除key對應(yīng)的node
     */
    public boolean removen(Integer key) {
        if (this.root != null) {
            Node node = searchNode(key, root);
            if (node == null) {
                return false;
            }
            removenNode(node);
            return true;
        }
        return false;
    }

    /**
     * @param node 刪除的節(jié)點
     */
    private void removenNode(Node node) {
        if (node == null) {
            return;
        }
        if (node.leftChild == null && node.rightChild == null) {    //情景1:若刪除結(jié)點無子結(jié)點,直接刪除。
            changeNode(node, null);
        } else if (node.leftChild != null && node.rightChild != null) { //情景3:若刪除結(jié)點有兩個子結(jié)點,用后繼結(jié)點(大于刪除結(jié)點的最小結(jié)點)替換刪除結(jié)點。
            Node rNode = node.rightChild;
            while (rNode.leftChild != null) {   //找到后繼結(jié)點
                rNode = rNode.leftChild;
            }
            //  交換位子
            /*if (rNode == node.rightChild) {
                node.rightChild = null;
                rNode.leftChild = node.leftChild;
            } else {
                if (rNode.rightChild != null) {    //后繼節(jié)點如果有右節(jié)點
                    rNode.parent.leftChild = rNode.rightChild;
                    rNode.rightChild.parent = rNode.parent;
                }
                rNode.leftChild = node.leftChild;
                rNode.rightChild = node.rightChild;
            }*/
            changeNode(node, rNode);    //用后繼節(jié)點替換要刪除節(jié)點
        } else { //情景2:若刪除結(jié)點只有一個子結(jié)點,用子結(jié)點替換刪除結(jié)點。
            if (node.leftChild != null) {
                changeNode(node, node.leftChild);
            } else {
                changeNode(node, node.rightChild);
            }
        }
    }

    /**
     * 兩節(jié)點位置交換
     * 交換后刪除替換節(jié)點fixupNode
     * @param delNode   要刪除節(jié)點
     * @param fixupNode 替換節(jié)點
     */
    private void changeNode(Node delNode, Node fixupNode) {
        RB_DELETE_FIXUP(fixupNode);

        if (fixupNode == null) {
            if (delNode.parent.leftChild == delNode) {
                delNode.parent.leftChild = null;
            } else {
                delNode.parent.rightChild = null;
            }
            return;
        }

        Object data = delNode.data;
        Color color = delNode.color;
        Integer key = delNode.key;
        if (delNode == root) {  // 交換時如果刪除節(jié)點是根節(jié)點,顏色直接改成黑色
            delNode.setColor(Color.BLACK);
        } else {
            delNode.color = fixupNode.color;
        }
        delNode.key = fixupNode.key;
        delNode.data = fixupNode.data;
        fixupNode.key = key;
        fixupNode.data = data;
        fixupNode.color = color;

        removenNode(fixupNode);
    }

    public Node searchNode(Integer key, Node node) {
        if (node == null)
            return null;
        if (node.key.compareTo(key) == 0) {
            return node;
        } else if (key.compareTo(node.key) < 0) {
            if (node.leftChild != null) {
                return searchNode(key, node.leftChild);
            }
            return null;
        } else {
            if (node.rightChild != null) {
                return searchNode(key, node.rightChild);
            }
            return null;
        }
    }

    private void RB_DELETE_FIXUP(Node fixupNode) {
        if (fixupNode == null || fixupNode.isRed()) {    //情景1:替換結(jié)點是紅色結(jié)點
            /*顏色變?yōu)閯h除結(jié)點的顏色*/
            return;
        } else {  //情景2:替換結(jié)點是黑結(jié)點
            Node bNode = fixupNode.parent.rightChild;
            if (fixupNode == fixupNode.parent.leftChild) { //情景2.1:替換結(jié)點是其父結(jié)點的左子結(jié)點
                //情景2.1.1:替換結(jié)點的兄弟結(jié)點是紅結(jié)點
                if (bNode.isRed()) {
                    bNode.setColor(Color.BLACK);
                    fixupNode.parent.setColor(Color.RED);
                    RRotate(fixupNode.parent);
                    RB_DELETE_FIXUP(fixupNode);
                } else {  //情景2.1.2: 替換結(jié)點的兄弟結(jié)點是黑結(jié)點
                    //情景2.1.2.1:替換結(jié)點的兄弟結(jié)點的右子結(jié)點是紅結(jié)點,左子結(jié)點任意顏色
                    if (bNode.rightChild != null && bNode.rightChild.isRed()) {
                        /*將S的顏色設(shè)為P的顏色 將P設(shè)為黑色 將SR設(shè)為黑色 對P進(jìn)行左旋*/
                        bNode.color = fixupNode.parent.color;
                        fixupNode.parent.setColor(Color.BLACK);
                        bNode.rightChild.setColor(Color.RED);
                        LRotate(fixupNode.parent);
                    } else if (bNode.leftChild != null && bNode.leftChild.isRed()) {
                        //情景2.1.2.2:替換結(jié)點的兄弟結(jié)點的右子結(jié)點為黑結(jié)點,左子結(jié)點為紅結(jié)點
                        /*將S設(shè)為紅色 將SL設(shè)為黑色 對S進(jìn)行右旋,得到情景2.1.2.1 進(jìn)行情景2.1.2.1的處理*/
                        bNode.setColor(Color.RED);
                        bNode.leftChild.setColor(Color.BLACK);
                        RRotate(bNode);
                        RB_DELETE_FIXUP(fixupNode);
                    } else {//刪除情景2.1.2.3: 替換結(jié)點的兄弟結(jié)點的子結(jié)點都為黑結(jié)點
                        /*將S設(shè)為紅色 把P作為新的替換結(jié)點 重新進(jìn)行刪除結(jié)點情景處理*/
                        bNode.setColor(Color.RED);
                        RB_DELETE_FIXUP(fixupNode.parent);
                    }

                }
            } else {
                //刪除情景2.2: 替換結(jié)點是其父結(jié)點的右子結(jié)點
                //刪除情景2.2.1: 替換結(jié)點的兄弟結(jié)點是紅結(jié)點
                if (bNode.isRed()) {
                    /*將S設(shè)為黑色 將P設(shè)為紅色 對P進(jìn)行右旋,得到情景2.2.2.3 進(jìn)行情景2.2.2.3的處理*/
                    bNode.setColor(Color.BLACK);
                    fixupNode.parent.setColor(Color.RED);
                    LRotate(fixupNode.parent);
                    RB_DELETE_FIXUP(fixupNode);
                } else { //刪除情景2.2.2: 替換結(jié)點的兄弟結(jié)點是黑結(jié)點
                    //刪除情景2.2.2.1: 替換結(jié)點的兄弟結(jié)點的左子結(jié)點是紅結(jié)點,右子結(jié)點任意顏色
                    if (bNode.leftChild != null && bNode.leftChild.isRed()) {
                        /*將S的顏色設(shè)為P的顏色 將P設(shè)為黑色 將SL設(shè)為黑色 對P進(jìn)行右旋*/
                        bNode.color = fixupNode.parent.color;
                        fixupNode.parent.setColor(Color.BLACK);
                        bNode.leftChild.setColor(Color.BLACK);
                        RRotate(fixupNode.parent);
                    } else if (bNode.rightChild != null && bNode.rightChild.isRed()) {//刪除情景2.2.2.2: 替換結(jié)點的兄弟結(jié)點的左子結(jié)點為黑結(jié)點,右子結(jié)點為紅結(jié)點
                        /*將S設(shè)為紅色 將SR設(shè)為黑色 對S進(jìn)行左旋,得到情景2.2.2.1 進(jìn)行情景2.2.2.1的處理*/
                        bNode.setColor(Color.RED);
                        bNode.rightChild.setColor(Color.BLACK);
                        LRotate(bNode);
                        RB_DELETE_FIXUP(fixupNode);
                    } else {//刪除情景2.2.2.3:替換結(jié)點的兄弟結(jié)點的子結(jié)點都為黑結(jié)點
                        /*將S設(shè)為紅色 把P作為新的替換結(jié)點 重新進(jìn)行刪除結(jié)點情景處理*/
                        bNode.setColor(Color.RED);
                        RB_DELETE_FIXUP(fixupNode.parent);
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        //int[] data={8,6,4};
        //int[] data={8,6,9,5,7,3};
        //int[] data={8,6,7};
        //int[] data={8,5,9,4,6,7};
        //int[] data={8,5,9,4,7,6};
        //int[] data = {8, 5, 9, 7, 6};
        //Object[] data = new Object[100];
        //Object[] data = {2, 4, 15, 11, 19, 3, "F", "G", "B", "A", "D", "C", "E", new Person("小王", 22)};
        /*for (int i = 0; i < 100; i++) {
            Random r = new Random();
            int n = r.nextInt(100);
            data[i] = "數(shù)據(jù)" + n;
            //System.out.println(n);
        }*/
        RBTree rbt = new RBTree();
        int[] data = {2, 4, 15, 11, 19, 3, 12, 14, 16, 9, 13, 17, 7, 8, 5, 1, 18, 6};
        for (int i = 0; i < data.length; i++) {
            if (data[i] == 9) {
                System.out.println();
            }
            System.out.println(data[i]);
            rbt.insertNode(data[i], data[i]);
            rbt.dlrTraversal();
            System.out.println("\n" + rbt.root.data);
        }
        rbt.removen(6);
        /*for (int i = 0; i < data.length; i++) {
            rbt.insertNode(String.valueOf(i), data[i]);
        }*/
        rbt.ldrTraversal();
        System.out.println("\n" + rbt.root.data);
        rbt.dlrTraversal();
        //System.out.println("\n" + rbt.search("0"));
    }
}

“java實現(xiàn)紅黑樹的代碼怎么寫”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI