一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 利用Java實現(xiàn)紅黑樹

利用Java實現(xiàn)紅黑樹

2022-01-03 16:59胡不慌 Java教程

紅黑樹是眾多“平衡的”搜索樹模式中的一種,在最壞情況下,它相關(guān)操作的時間復(fù)雜度為O(log n),接下倆小編將子啊下文詳細(xì)介紹Java是如何實現(xiàn)紅黑樹的

 

1、紅黑樹的屬性

紅黑樹是一種二分查找樹,與普通的二分查找樹不同的一點是,紅黑樹的每個節(jié)點都有一個顏色(color)屬性。該屬性的值要么是紅色,要么是黑色。

通過限制從根到葉子的任何簡單路徑上的節(jié)點顏色,紅黑樹確保沒有比任何其他路徑長兩倍的路徑,從而使樹近似平衡。

假設(shè)紅黑樹節(jié)點的屬性有鍵(key)、顏色(color)、左子節(jié)點(left)、右子節(jié)點(right),父節(jié)點(parent)。

一棵紅黑樹必須滿足下面有下面這些特性( 紅黑樹特性 ):

  • 樹中的每個節(jié)點要么是紅色,要么是黑色;
  • 根節(jié)點是黑色;
  • 每個葉子節(jié)點(null)是黑色;
  • 如果某節(jié)點是紅色的,它的兩個子節(jié)點都是黑色;
  • 對于每個節(jié)點到后面任一葉子節(jié)點(null)的所有路徑,都有相同數(shù)量的黑色節(jié)點。

為了在紅黑樹代碼中處理邊界條件方便,我們用一個哨兵變量代替null。對于一個紅黑樹tree,哨兵變量RedBlackTree.NULL(下文代碼中)是一個和其它節(jié)點有同樣屬性的節(jié)點,它的顏色(color)屬性是黑色,其它屬性可以任意取值。

我們使用哨兵變量是因為我們可以把一個節(jié)點node的子節(jié)點null當(dāng)成一個普通節(jié)點。

在這里,我們使用哨兵變量RedBlackTree.NULL代替樹中所有的null(所有的葉子節(jié)點及根節(jié)點的父節(jié)點)。

我們把從一個節(jié)點n(不包括)到任一葉子節(jié)點路徑上的黑色節(jié)點的個數(shù)稱為 黑色高度 ,用bh(n)表示。一棵紅黑樹的黑色高度是其根節(jié)點的黑色高度。

關(guān)于紅黑樹的搜索,求最小值,求最大值,求前驅(qū),求后繼這些操作的代碼與二分查找樹的這些操作的代碼基本一致。可以在用java實現(xiàn)二分查找樹查看。

結(jié)合上文給出下面的代碼。

用一個枚舉類Color表示顏色:

public enum Color {
    Black("黑色"), Red("紅色");

    private String color;

    private Color(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return color;
    }
}

類Node表示節(jié)點:

public class Node {
    public int key;
    public Color color;
    public Node left;
    public Node right;
    public Node parent;

    public Node() {
    }

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

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

    public int height() {
        return Math.max(left != RedBlackTree.NULL ? left.height() : 0, right != RedBlackTree.NULL ? right.height() : 0) + 1;
    }

    public Node minimum() {
        Node pointer = this;
        while (pointer.left != RedBlackTree.NULL)
            pointer = pointer.left;
        return pointer;
    }

    @Override
    public String toString() {
        String position = "null";
        if (this.parent != RedBlackTree.NULL)
            position = this.parent.left == this ? "left" : "right";
        return "[key: " + key + ", color: " + color + ", parent: " + parent.key + ", position: " + position + "]";
    }
}

類RedTreeNode表示紅黑樹:

public class RedBlackTree {

    // 表示哨兵變量
    public final static Node NULL = new Node(Color.Black);

    public Node root;

    public RedBlackTree() {
        this.root = NULL;
    }

}

 

2、旋轉(zhuǎn)

紅黑樹的插入和刪除操作,能改變紅黑樹的結(jié)構(gòu),可能會使它不再有前面所說的某些特性性。為了維持這些特性,我們需要改變樹中某些節(jié)點的顏色和位置。

我們可以通過旋轉(zhuǎn)改變節(jié)點的結(jié)構(gòu)。主要有 左旋轉(zhuǎn) 右旋轉(zhuǎn) 兩種方式。具體如下圖所示。

左旋轉(zhuǎn):把一個節(jié)點n的右子節(jié)點right變?yōu)樗母腹?jié)點,n變?yōu)閞ight的左子節(jié)點,所以right不能為null。這時n的右指針空了出來,right的左子樹被n擠掉,所以right原來的左子樹稱為n的右子樹。

右旋轉(zhuǎn):把一個節(jié)點n的左子節(jié)點left變?yōu)樗母腹?jié)點,n變?yōu)閘eft的右子節(jié)點,所以left不能為null。這時n的左指針被空了出來,left的右子樹被n擠掉,所以left原來的右子樹被稱為n的左子樹。

利用Java實現(xiàn)紅黑樹

可在RedTreeNode類中,加上如下實現(xiàn)代碼:

public void leftRotate(Node node) {
        Node rightNode = node.right;

        node.right = rightNode.left;
        if (rightNode.left != RedBlackTree.NULL)
            rightNode.left.parent = node;

        rightNode.parent = node.parent;
        if (node.parent == RedBlackTree.NULL)
            this.root = rightNode;
        else if (node.parent.left == node)
            node.parent.left = rightNode;
        else
            node.parent.right = rightNode;

        rightNode.left = node;
        node.parent = rightNode;
    }

    public void rightRotate(Node node) {
        Node leftNode = node.left;

        node.left = leftNode.right;
        if (leftNode.right != RedBlackTree.NULL)
            leftNode.right.parent = node;

        leftNode.parent = node.parent;
        if (node.parent == RedBlackTree.NULL) {
            this.root = leftNode;
        } else if (node.parent.left == node) {
            node.parent.left = leftNode;
        } else {
            node.parent.right = leftNode;
        }

        leftNode.right = node;
        node.parent = leftNode;
    }

 

3、插入

紅黑樹的插入代碼與二分查找樹的插入代碼非常相似。只不過紅黑樹的插入操作會改變紅黑樹的結(jié)構(gòu),使其不在有該有的特性。

在這里,新插入的節(jié)點默認(rèn)是紅色。

所以在插入節(jié)點之后,要有維護(hù)紅黑樹特性的代碼。

public void insert(Node node) {
        Node parentPointer = RedBlackTree.NULL;
        Node pointer = this.root;

        while (this.root != RedBlackTree.NULL) {
            parentPointer = pointer;
            pointer = node.key < pointer.key ? pointer.left : pointer.right;
        }

        node.parent = parentPointer;
        if(parentPointer == RedBlackTree.NULL) {
            this.root = node;
        }else if(node.key < parentPointer.key) {
            parentPointer.left = node;
        }else {
            parentPointer.right = node;
        }

        node.left = RedBlackTree.NULL;
        node.right = RedBlackTree.NULL;
        node.color = Color.Red;
        // 維護(hù)紅黑樹屬性的方法
        this.insertFixUp(node);
    }

用上述方法插入一個新節(jié)點的時候,有兩類情況會違反紅黑樹的特性。

  • 當(dāng)樹中沒有節(jié)點時,此時插入的節(jié)點稱為根節(jié)點,而此節(jié)點的顏色為紅色。
  • 當(dāng)新插入的節(jié)點成為一個紅色節(jié)點的子節(jié)點時,此時存在一個紅色結(jié)點有紅色子節(jié)點的情況。
  •  

對于第一類情況,可以直接把根結(jié)點設(shè)置為黑色;而針對第二類情況,需要根據(jù)具體條件,做出相應(yīng)的解決方案。

具體代碼如下:

public void insertFixUp(Node node) {
        // 當(dāng)node不是根結(jié)點,且node的父節(jié)點顏色為紅色
        while (node.parent.color == Color.Red) {
            // 先判斷node的父節(jié)點是左子節(jié)點,還是右子節(jié)點,這不同的情況,解決方案也會不同
            if (node.parent == node.parent.parent.left) {
                Node uncleNode = node.parent.parent.right;
                if (uncleNode.color == Color.Red) {  // 如果叔叔節(jié)點是紅色,則父父一定是黑色
                    // 通過把父父節(jié)點變成紅色,父節(jié)點和兄弟節(jié)點變成黑色,然后在判斷父父節(jié)點的顏色是否合適
                    uncleNode.color = Color.Black;
                    node.parent.color = Color.Black;
                    node.parent.parent.color = Color.Red;
                    node = node.parent.parent;
                } else if (node == node.parent.right) {
                    node = node.parent;
                    this.leftRotate(node);
                } else {
                    node.parent.color = Color.Black;
                    node.parent.parent.color = Color.Red;
                    this.rightRotate(node.parent.parent);
                }
            } else {
                Node uncleNode = node.parent.parent.left;
                if (uncleNode.color == Color.Red) {
                    uncleNode.color = Color.Black;
                    node.parent.color = Color.Black;
                    node.parent.parent.color = Color.Red;
                    node = node.parent.parent;
                } else if (node == node.parent.left) {
                    node = node.parent;
                    this.rightRotate(node);
                } else {
                    node.parent.color = Color.Black;
                    node.parent.parent.color = Color.Red;
                    this.leftRotate(node.parent.parent);
                }
            }
        }
        // 如果之前樹中沒有節(jié)點,那么新加入的點就成了新結(jié)點,而新插入的結(jié)點都是紅色的,所以需要修改。
        this.root.color = Color.Black;
    }

下面的圖分別對應(yīng)第二類情況中的六種及相應(yīng)處理結(jié)果。

情況1:

利用Java實現(xiàn)紅黑樹

情況2:

利用Java實現(xiàn)紅黑樹

情況3:

利用Java實現(xiàn)紅黑樹

情況4:

利用Java實現(xiàn)紅黑樹

情況5:

利用Java實現(xiàn)紅黑樹

情況6:

利用Java實現(xiàn)紅黑樹

 

4、刪除

紅黑樹中節(jié)點的刪除會使一個結(jié)點代替另外一個節(jié)點。所以先要實現(xiàn)這樣的代碼:

public void transplant(Node n1, Node n2) {
        if(n1.parent == RedBlackTree.NULL){
            this.root = n2;
        }else if(n1.parent.left == n1) {
            n1.parent.left = n2;
        }else {
            n1.parent.right = n2;
        }
        n2.parent = n1.parent;
    }


紅黑樹的刪除節(jié)點代碼是基于二分查找樹的刪除節(jié)點代碼而寫的。

刪除結(jié)點代碼:

public void delete(Node node) {
        Node pointer1 = node;
        // 用于記錄被刪除的顏色,如果是紅色,可以不用管,但如果是黑色,可能會破壞紅黑樹的屬性
        Color pointerOriginColor = pointer1.color;
        // 用于記錄問題的出現(xiàn)點
        Node pointer2;
        if (node.left == RedBlackTree.NULL) {
            pointer2 = node.right;
            this.transplant(node, node.right);
        } else if (node.right == RedBlackTree.NULL) {
            pointer2 = node.left;
            this.transplant(node, node.left);
        } else {
            // 如要刪除的字節(jié)有兩個子節(jié)點,則找到其直接后繼(右子樹最小值),直接后繼節(jié)點沒有非空左子節(jié)點。
            pointer1 = node.right.minimum();
            // 記錄直接后繼的顏色和其右子節(jié)點
            pointerOriginColor = pointer1.color;
            pointer2 = pointer1.right;
            // 如果其直接后繼是node的右子節(jié)點,不用進(jìn)行處理
            if (pointer1.parent == node) {
                pointer2.parent = pointer1;
            } else {
                // 否則,先把直接后繼從樹中提取出來,用來替換node
                this.transplant(pointer1, pointer1.right);
                pointer1.right = node.right;
                pointer1.right.parent = pointer1;
            }
            // 用node的直接后繼替換node,繼承node的顏色
            this.transplant(node, pointer1);
            pointer1.left = node.left;
            pointer1.left.parent = pointer1;
            pointer1.color = node.color;
        }
        if (pointerOriginColor == Color.Black) {
            this.deleteFixUp(pointer2);
        }
    }

當(dāng)被刪除節(jié)點的顏色是黑色時需要調(diào)用方法維護(hù)紅黑樹的特性。

主要有兩類情況:

  • 當(dāng)node是紅色時,直接變成黑色即可。
  • 當(dāng)node是黑色時,需要調(diào)整紅黑樹結(jié)構(gòu)。,
private void deleteFixUp(Node node) {
        // 如果node不是根節(jié)點,且是黑色
        while (node != this.root && node.color == Color.Black) {
            // 如果node是其父節(jié)點的左子節(jié)點
            if (node == node.parent.left) {
                // 記錄node的兄弟節(jié)點
                Node pointer1 = node.parent.right;
                // 如果他兄弟節(jié)點是紅色
                if (pointer1.color == Color.Red) {
                    pointer1.color = Color.Black;
                    node.parent.color = Color.Red;
                    leftRotate(node.parent);
                    pointer1 = node.parent.right;
                }
                if (pointer1.left.color == Color.Black && pointer1.right.color == Color.Black) {
                    pointer1.color = Color.Red;
                    node = node.parent;
                } else if (pointer1.right.color == Color.Black) {
                    pointer1.left.color = Color.Black;
                    pointer1.color = Color.Red;
                    rightRotate(pointer1);
                    pointer1 = node.parent.right;
                } else {
                    pointer1.color = node.parent.color;
                    node.parent.color = Color.Black;
                    pointer1.right.color = Color.Black;
                    leftRotate(node.parent);
                    node = this.root;
                }
            } else {
                // 記錄node的兄弟節(jié)點
                Node pointer1 = node.parent.left;
                // 如果他兄弟節(jié)點是紅色
                if (pointer1.color == Color.Red) {
                    pointer1.color = Color.Black;
                    node.parent.color = Color.Red;
                    rightRotate(node.parent);
                    pointer1 = node.parent.left;
                }
                if (pointer1.right.color == Color.Black && pointer1.left.color == Color.Black) {
                    pointer1.color = Color.Red;
                    node = node.parent;
                } else if (pointer1.left.color == Color.Black) {
                    pointer1.right.color = Color.Black;
                    pointer1.color = Color.Red;
                    leftRotate(pointer1);
                    pointer1 = node.parent.left;
                } else {
                    pointer1.color = node.parent.color;
                    node.parent.color = Color.Black;
                    pointer1.left.color = Color.Black;
                    rightRotate(node.parent);
                    node = this.root;
                }
            }

        }
        node.color = Color.Black;
    }

對第二類情況,有下面8種:

情況1:

利用Java實現(xiàn)紅黑樹

情況2:

利用Java實現(xiàn)紅黑樹

情況3:

利用Java實現(xiàn)紅黑樹

情況4:

利用Java實現(xiàn)紅黑樹

情況5:

利用Java實現(xiàn)紅黑樹

情況6:

利用Java實現(xiàn)紅黑樹

情況7:

利用Java實現(xiàn)紅黑樹

情況8:

利用Java實現(xiàn)紅黑樹

 

5、所有代碼

public enum Color {
    Black("黑色"), Red("紅色");

    private String color;

    private Color(String color) {
        this.color = color;
    }

    @Override
    public String toString() {
        return color;
    }
}
public class Node {
    public int key;
    public Color color;
    public Node left;
    public Node right;
    public Node parent;

    public Node() {
    }

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

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

    /**
     * 求在樹中節(jié)點的高度
     * 
     * @return
     */
    public int height() {
        return Math.max(left != RedBlackTree.NULL ? left.height() : 0, right != RedBlackTree.NULL ? right.height() : 0) + 1;
    }

    /**
     * 在以該節(jié)點為根節(jié)點的樹中,求最小節(jié)點
     * 
     * @return
     */
    public Node minimum() {
        Node pointer = this;
        while (pointer.left != RedBlackTree.NULL)
            pointer = pointer.left;
        return pointer;
    }

    @Override
    public String toString() {
        String position = "null";
        if (this.parent != RedBlackTree.NULL)
            position = this.parent.left == this ? "left" : "right";
        return "[key: " + key + ", color: " + color + ", parent: " + parent.key + ", position: " + position + "]";
    }
}
import java.util.LinkedList;
import java.util.Queue;

public class RedBlackTree {

    public final static Node NULL = new Node(Color.Black);

    public Node root;

    public RedBlackTree() {
        this.root = NULL;
    }

    /**
     * 左旋轉(zhuǎn)
     * 
     * @param node
     */
    public void leftRotate(Node node) {
        Node rightNode = node.right;

        node.right = rightNode.left;
        if (rightNode.left != RedBlackTree.NULL)
            rightNode.left.parent = node;

        rightNode.parent = node.parent;
        if (node.parent == RedBlackTree.NULL)
            this.root = rightNode;
        else if (node.parent.left == node)
            node.parent.left = rightNode;
        else
            node.parent.right = rightNode;

        rightNode.left = node;
        node.parent = rightNode;
    }

    /**
     * 右旋轉(zhuǎn)
     * 
     * @param node
     */
    public void rightRotate(Node node) {
        Node leftNode = node.left;

        node.left = leftNode.right;
        if (leftNode.right != RedBlackTree.NULL)
            leftNode.right.parent = node;

        leftNode.parent = node.parent;
        if (node.parent == RedBlackTree.NULL) {
            this.root = leftNode;
        } else if (node.parent.left == node) {
            node.parent.left = leftNode;
        } else {
            node.parent.right = leftNode;
        }

        leftNode.right = node;
        node.parent = leftNode;
    }

    public void insert(Node node) {
        Node parentPointer = RedBlackTree.NULL;
        Node pointer = this.root;

        while (pointer != RedBlackTree.NULL) {
            parentPointer = pointer;
            pointer = node.key < pointer.key ? pointer.left : pointer.right;
        }

        node.parent = parentPointer;
        if (parentPointer == RedBlackTree.NULL) {
            this.root = node;
        } else if (node.key < parentPointer.key) {
            parentPointer.left = node;
        } else {
            parentPointer.right = node;
        }

        node.left = RedBlackTree.NULL;
        node.right = RedBlackTree.NULL;
        node.color = Color.Red;
        this.insertFixUp(node);
    }

    private void insertFixUp(Node node) {
        // 當(dāng)node不是根結(jié)點,且node的父節(jié)點顏色為紅色
        while (node.parent.color == Color.Red) {
            // 先判斷node的父節(jié)點是左子節(jié)點,還是右子節(jié)點,這不同的情況,解決方案也會不同
            if (node.parent == node.parent.parent.left) {
                Node uncleNode = node.parent.parent.right;
                if (uncleNode.color == Color.Red) { // 如果叔叔節(jié)點是紅色,則父父一定是黑色
                    // 通過把父父節(jié)點變成紅色,父節(jié)點和兄弟節(jié)點變成黑色,然后在判斷父父節(jié)點的顏色是否合適
                    uncleNode.color = Color.Black;
                    node.parent.color = Color.Black;
                    node.parent.parent.color = Color.Red;
                    node = node.parent.parent;
                } else if (node == node.parent.right) { // node是其父節(jié)點的右子節(jié)點,且叔叔節(jié)點是黑色
                    // 對node的父節(jié)點進(jìn)行左旋轉(zhuǎn)
                    node = node.parent;
                    this.leftRotate(node);
                } else { // node如果叔叔節(jié)點是黑色,node是其父節(jié)點的左子節(jié)點,父父節(jié)點是黑色
                    // 把父節(jié)點變成黑色,父父節(jié)點變成紅色,對父父節(jié)點進(jìn)行右旋轉(zhuǎn)
                    node.parent.color = Color.Black;
                    node.parent.parent.color = Color.Red;
                    this.rightRotate(node.parent.parent);
                }
            } else {
                Node uncleNode = node.parent.parent.left;
                if (uncleNode.color == Color.Red) {
                    uncleNode.color = Color.Black;
                    node.parent.color = Color.Black;
                    node.parent.parent.color = Color.Red;
                    node = node.parent.parent;
                } else if (node == node.parent.left) {
                    node = node.parent;
                    this.rightRotate(node);
                } else {
                    node.parent.color = Color.Black;
                    node.parent.parent.color = Color.Red;
                    this.leftRotate(node.parent.parent);
                }
            }
        }
        // 如果之前樹中沒有節(jié)點,那么新加入的點就成了新結(jié)點,而新插入的結(jié)點都是紅色的,所以需要修改。
        this.root.color = Color.Black;
    }

    /**
     * n2替代n1
     * 
     * @param n1
     * @param n2
     */
    private void transplant(Node n1, Node n2) {

        if (n1.parent == RedBlackTree.NULL) { // 如果n1是根節(jié)點
            this.root = n2;
        } else if (n1.parent.left == n1) { // 如果n1是其父節(jié)點的左子節(jié)點
            n1.parent.left = n2;
        } else { // 如果n1是其父節(jié)點的右子節(jié)點
            n1.parent.right = n2;
        }
        n2.parent = n1.parent;
    }

    /**
     * 刪除節(jié)點node
     * 
     * @param node
     */
    public void delete(Node node) {
        Node pointer1 = node;
        // 用于記錄被刪除的顏色,如果是紅色,可以不用管,但如果是黑色,可能會破壞紅黑樹的屬性
        Color pointerOriginColor = pointer1.color;
        // 用于記錄問題的出現(xiàn)點
        Node pointer2;
        if (node.left == RedBlackTree.NULL) {
            pointer2 = node.right;
            this.transplant(node, node.right);
        } else if (node.right == RedBlackTree.NULL) {
            pointer2 = node.left;
            this.transplant(node, node.left);
        } else {
            // 如要刪除的字節(jié)有兩個子節(jié)點,則找到其直接后繼(右子樹最小值),直接后繼節(jié)點沒有非空左子節(jié)點。
            pointer1 = node.right.minimum();
            // 記錄直接后繼的顏色和其右子節(jié)點
            pointerOriginColor = pointer1.color;
            pointer2 = pointer1.right;
            // 如果其直接后繼是node的右子節(jié)點,不用進(jìn)行處理
            if (pointer1.parent == node) {
                pointer2.parent = pointer1;
            } else {
                // 否則,先把直接后繼從樹中提取出來,用來替換node
                this.transplant(pointer1, pointer1.right);
                pointer1.right = node.right;
                pointer1.right.parent = pointer1;
            }
            // 用node的直接后繼替換node,繼承node的顏色
            this.transplant(node, pointer1);
            pointer1.left = node.left;
            pointer1.left.parent = pointer1;
            pointer1.color = node.color;
        }
        if (pointerOriginColor == Color.Black) {
            this.deleteFixUp(pointer2);
        }
    }

    /**
     * The procedure RB-DELETE-FIXUP restores properties 1, 2, and 4
     * 
     * @param node
     */
    private void deleteFixUp(Node node) {
        // 如果node不是根節(jié)點,且是黑色
        while (node != this.root && node.color == Color.Black) {
            // 如果node是其父節(jié)點的左子節(jié)點
            if (node == node.parent.left) {
                // 記錄node的兄弟節(jié)點
                Node pointer1 = node.parent.right;
                // 如果node兄弟節(jié)點是紅色
                if (pointer1.color == Color.Red) {
                    pointer1.color = Color.Black;
                    node.parent.color = Color.Red;
                    leftRotate(node.parent);
                    pointer1 = node.parent.right;
                }
                if (pointer1.left.color == Color.Black && pointer1.right.color == Color.Black) {
                    pointer1.color = Color.Red;
                    node = node.parent;
                } else if (pointer1.right.color == Color.Black) {
                    pointer1.left.color = Color.Black;
                    pointer1.color = Color.Red;
                    rightRotate(pointer1);
                    pointer1 = node.parent.right;
                } else {
                    pointer1.color = node.parent.color;
                    node.parent.color = Color.Black;
                    pointer1.right.color = Color.Black;
                    leftRotate(node.parent);
                    node = this.root;
                }
            } else {
                // 記錄node的兄弟節(jié)點
                Node pointer1 = node.parent.left;
                // 如果他兄弟節(jié)點是紅色
                if (pointer1.color == Color.Red) {
                    pointer1.color = Color.Black;
                    node.parent.color = Color.Red;
                    rightRotate(node.parent);
                    pointer1 = node.parent.left;
                }
                if (pointer1.right.color == Color.Black && pointer1.left.color == Color.Black) {
                    pointer1.color = Color.Red;
                    node = node.parent;
                } else if (pointer1.left.color == Color.Black) {
                    pointer1.right.color = Color.Black;
                    pointer1.color = Color.Red;
                    leftRotate(pointer1);
                    pointer1 = node.parent.left;
                } else {
                    pointer1.color = node.parent.color;
                    node.parent.color = Color.Black;
                    pointer1.left.color = Color.Black;
                    rightRotate(node.parent);
                    node = this.root;
                }
            }

        }
        node.color = Color.Black;
    }

    private void innerWalk(Node node) {
        if (node != NULL) {
            innerWalk(node.left);
            System.out.println(node);
            innerWalk(node.right);
        }
    }

    /**
     * 中序遍歷
     */
    public void innerWalk() {
        this.innerWalk(this.root);
    }

    /**
     * 層次遍歷
     */
    public void print() {
        Queue<Node> queue = new LinkedList<>();
        queue.add(this.root);
        while (!queue.isEmpty()) {
            Node temp = queue.poll();
            System.out.println(temp);
            if (temp.left != NULL)
                queue.add(temp.left);
            if (temp.right != NULL)
                queue.add(temp.right);
        }
    }

    // 查找
    public Node search(int key) {
        Node pointer = this.root;
        while (pointer != NULL && pointer.key != key) {
            pointer = pointer.key < key ? pointer.right : pointer.left;
        }
        return pointer;
    }

}

 

6、演示

演示代碼:

public class Test01 {
  public static void main(String[] args) {
    int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8 };
    RedBlackTree redBlackTree = new RedBlackTree();
    for (int i = 0; i < arr.length; i++) {
      redBlackTree.insert(new Node(arr[i]));
    }
    System.out.println("樹的高度: " + redBlackTree.root.height());
    System.out.println("左子樹的高度: " + redBlackTree.root.left.height());
    System.out.println("右子樹的高度: " + redBlackTree.root.right.height());
    System.out.println("層次遍歷");
    redBlackTree.print();
    // 要刪除節(jié)點
    Node node = redBlackTree.search(4);
    redBlackTree.delete(node);
    System.out.println("樹的高度: " + redBlackTree.root.height());
    System.out.println("左子樹的高度: " + redBlackTree.root.left.height());
    System.out.println("右子樹的高度: " + redBlackTree.root.right.height());
    System.out.println("層次遍歷");
    redBlackTree.print();
  }
}

到此這篇關(guān)于利用Java實現(xiàn)紅黑樹的文章就介紹到這了,更多相關(guān)Java實現(xiàn)紅黑樹內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://www.tuicool.com/articles/RnAjqev

延伸 · 閱讀

精彩推薦
  • Java教程xml與Java對象的轉(zhuǎn)換詳解

    xml與Java對象的轉(zhuǎn)換詳解

    這篇文章主要介紹了xml與Java對象的轉(zhuǎn)換詳解的相關(guān)資料,需要的朋友可以參考下...

    Java教程網(wǎng)2942020-09-17
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java實現(xiàn)搶紅包功能

    Java實現(xiàn)搶紅包功能

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發(fā)現(xiàn)了對于集合操作轉(zhuǎn)換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關(guān)于Java8中S...

    阿杜7482021-02-04
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關(guān)于小米推送Java代碼,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩(wěn)中求8032021-07-12
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發(fā)項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經(jīng)有好久沒有升過級了。升級完畢重啟之后,突然發(fā)現(xiàn)好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java BufferWriter寫文件寫不進(jìn)去或缺失數(shù)據(jù)的解決

    Java BufferWriter寫文件寫不進(jìn)去或缺失數(shù)據(jù)的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進(jìn)去或缺失數(shù)據(jù)的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
主站蜘蛛池模板: 小SAO货叫大声点妓女 | 久久免费看少妇高潮A片2012 | 四虎1515h永久 | 四虎国产一区 | 国产麻豆精品入口在线观看 | 岛国a香蕉片不卡在线观看 荡女淫春2古装 | 天天插在线视频 | 日韩欧美在线一区二区三区 | 国产成人在线视频 | 美味情缘韩国在线观看视频 | 国产精品对白刺激久久久 | 亚洲国产精品高清在线 | 成人福利免费在线观看 | 日本动漫xxxxxx | 香蕉tv亚洲专区在线观看 | 日韩成人小视频 | 亚洲精品福利一区二区在线观看 | 男女男精品网站免费观看 | 色臀网站| 亚洲精品一线二线三线 | 国语刺激对白勾搭视频在线观看 | 草莓香蕉榴莲丝瓜秋葵绿巨人在线看 | 精品久久久久久久高清 | 日本护士撒尿xxxx18 | 东北老女人91p0rny | 青青网| 亚洲精品视频一区 | 亚洲欧美在线免费观看 | 99久久精品自在自看国产 | 四虎影院免费视频 | 国产欧美在线播放 | av91在线| 毛片小视频 | 国自产拍在线天天更新91 | 视频免费视频观看网站 | 99色在线观看 | 无人区大片免费播放器 | ipx 在线播放| 国产精品国产香蕉在线观看网 | 欧美日韩一区二区中文字幕视频 | 国产午夜视频在线观看网站 |