紅黑樹:整理學習

紅黑樹

紅黑樹定義

  • 紅色結點均爲左節點 – 紅色結點與黑色結點合併會得到一個-3結點
  • 沒有任何一個結點同時和兩個紅色結點相連
  • 任一空連接到根節點的長度和黑色結點的數目相同

image-20200615192130835

結點定義

// 紅色結點記爲true,黑色記爲false
private static final boolean RED = true;
private static final boolean BLACK = false;

// BST helper node data type
private class Node {
    private Key key;           // key
    private Value val;         // associated data
    private Node left, right;  // links to left and right subtrees
    private boolean color;     // color of parent link
    private int size;          // subtree count

    public Node(Key key, Value val, boolean color, int size) {
        this.key = key;
        this.val = val;
        this.color = color;
        this.size = size;
    }
}


紅黑樹的左旋與右旋,以及顏色變換:

private Node rotateLeft(Node h) {
    Node x = h.right;
    x.left = h;
    x.color = h.color;
    // 與父節點鏈接變爲紅色
    h.color = RED;
    x.size = size(h.left) + size(h.right) + 1;
    return x;
}

private Node rotateRight(Node h) {
    Node x = h.left;
    h.left = x.right;
    x.right = h;
    x.color = h.color;
    h.color = RED;
    x.size = size(h.left) + size(h.right) + 1;
    return x;
}

private void flipColors(Node h) {
    if (h == null) return;
    h.color = RED;
    h.left.color = BLACK;
    h.right.color = BLACK;
}

紅黑樹插入算法的關鍵:

  • 要在一個3-結點下面插入一個新節點,需要將結點臨時轉換成一個4-結點
  • 將其分解並將紅鏈接由中間鍵傳遞給父節點
  • 直到遇見一個2-結點或根節點
private void put(Key key, Value val) {
    root = put(root, key, val);
    root.color = BLACK;
}

private Node put(Node h, Key key, Value val) {
    // 如果沒有則插入一個紅色結點,這樣方便以後調整
    if (h == null)
        return new Node(key, val, RED, 1);

    int cmp = key.compareTo(h.key);

    // 滿足BST的性質,如果小於,則從左邊插入
    if (cmp < 0) h.left = put(h.left, key, val);
    else if (cmp > 0) h.right = put(h.right, key, val);
    // 已經在樹中,更新值
    else h.val = val;

    /**
     * 紅黑樹調整的目的是爲了在插入結點的同時動態調整樹的高度
     * 避免樹的高度過高,提升索引的效率
     */

    // 重點!! 紅黑樹的調整過程
    // 左黑右紅
    if (!isRed(h.left) && isRed(h.right))
        h = rotateLeft(h); // 左旋
    // 左紅右黑
    if (isRed(h.left) && !isRed(h.right))
        h = rotateRight(h); // 右旋
    // 全紅
    if (isRed(h.left) && isRed(h.right))
        flipColors(h); // 顏色反轉 -- 結點成爲2-結點,父節點成爲3-結點

    // 調整樹的規模
    h.size = size(h.left) + size(h.right) + 1;
    return h;
}

刪除算法之後補充

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