Red-black tree data structure explanation (with Java implementation code)

2-3 search tree definition

1. The path length of any empty link to the root node is equal
2. When the 4-node is transformed into a 3-node, the height of the tree will not change, only when the root node is a temporary 4-node, After decomposing the root node, the height of the tree is +1
3. Ordinary binary search trees grow from top to bottom, and the bottom-up growth of
Insert picture description here
Insert picture description here
2-3 search trees are all 2-3 search trees
(generated during node insertion 4- The node is temporary!)

Red-black tree definition

On the premise of satisfying 2-3 search tree, use == "mark" == to link between nodes.
There are two colors:
red Simulate the 3-node in the 2-3 search tree
black Ordinary node link form

nature:

  1. Red links are all left connections
    2. No node is connected to two red links at the same time (4-node does not exist)
    3. Any empty link to the root node passes through the same black link

In this way, the red-black tree can maintain a wonderful balance while inserting nodes.
With this knowledge, start to build your own red-black tree!

Left-hand and right-hand

When the left child node of a node is black and the right child node is red, it needs to be left-handed. For
example, in the figure below, insert a node with a value of 50
Insert picture description here

By turning left. We can make only the left link red ,
but the
following situation will appear:

Insert picture description here
This violates the rule 1 of the red-black tree , so we still have to operate, then perform right-hand
|
|
|
Insert picture description here
But found that it still violates the rule 2,
so continue to operate

Color inversion

The above operation produces two red link node (4- corresponding to the node in the binary tree), at this time, we need to continue to operate this node so as to satisfy the rule 2 .
Look at the following this Figure After
inserting S, AES (4-node) is formed, and then the 4-node is decomposed
Insert picture description here
.
Insert picture description here
Let's take a look at this figure at this time: Is there the same place (think of it as 4 above) -Node)
Insert picture description here
Now continue to operate on this node:
Insert picture description here
Seeing this, you may be a little confused: Why is the two red links black?
Don't worry, see below

If there is a node with 50 elements, the
Insert picture description here
result is different. This is because we stipulate: The link of the root node always points to itself, and the root link is always black.
See here, what the code needs to achieve is to find the position to insert the element. And place the node, and successively ** (left-handed, right-handed, color inversion) ------ (if necessary) ** can maintain the balance of the red and black tree
Code:

Java implementation code

package cn.datastructure.structure.tree;

/**
 * @author 悠一木碧
 * 红黑树实现:
 * 基于了2-3查找树的思想:
 * 任意空链接到根节点的路径长度都是相等的
 * 4-结点变换为3-结点时, 树的高度不会发生变化, 只有当根节点是临时的4-结点时, 分解根节点后, 树的高度+1
 * 普通二叉查找树是自顶向下生长的, 2-3查找树的自底向上生长的
 * 且:
 * 红链接均为左连接
 * 没有任何一个结点同时与两个红链接相连
 * 任意空链接到根节点的路径经过相同的黑链接
 */
public class RedBlackTree<Key extends Comparable<Key>, Value> {
    
    
    private Node root;
    private int size;
    private final boolean RED = true;
    private final boolean BLACK = false;

    private class Node{
    
    
        public Key key;
        public Value value;
        public Node left;
        public Node right;
//        用来标识父节点指向自己链接的颜色
        public boolean color;

        public Node(Key key, Value value, Node left, Node right, boolean color) {
    
    
            this.key = key;
            this.value = value;
            this.left = left;
            this.right = right;
            this.color = color;
        }

        public Node() {
    
    
        }

    }


//  将根链接的颜色永远设置为黑色
    public void put(Key key, Value value){
    
    
        root = put(root, key, value);
        this.root.color = BLACK;
    }

//  在node结点下完成插入操作, 是个递归方法
    private Node put(Node node, Key key, Value value){
    
    
        if(null == node){
    
    
            size++;
            return new Node(key, value, null, null, BLACK);
        }
        if(key.compareTo(node.key) < 0){
    
    
            node.left = put(node.left, key, value);
        } else if(key.compareTo(node.key) > 0){
    
    
            node.right = put(node.right, key, value);
        } else{
    
    
            node.value = value;
        }

        if(isRed(node.right) && !isRed(node.left)){
    
    
            rotateLeft(node);
        }
        if(isRed(node.left) && isRed(node.left.left)){
    
    
            rotateRight(node);
        }
        if(isRed(node.left) && isRed(node.right)){
    
    
            colorInversion(node);
        }
        return node;
    }

    /**
     * 左旋操作,
     * @param head
     */
    private Node rotateLeft(Node head){
    
    
        Node rightSon = head.right;
        head.right = rightSon.left;
        rightSon.left = head;
        rightSon.color = head.color;
        head.color = RED;
        return rightSon;
    }

    /**
     * 右旋操作
     * @param head
     * @return
     */
    private Node rotateRight(Node head){
    
    
        Node leftSon = head.left;
        head.left = leftSon.right;
        leftSon.right = head;
        leftSon.color = head.color;
        head.color = RED;
        return leftSon;
    }

    /**
     * 空链接默认为黑色
     * @param node
     * @return
     */
    private boolean isRed(Node node){
    
    
        if(null == node){
    
    
            return false;
        }
        return node.color == RED;
    }


    /**
     * 相当于拆分掉4-结点, 在红黑树中, 临时的4-结点相当于当前结点的左右链接都是红色
     * @param node
     */
    private void colorInversion(Node node){
    
    
        node.color = RED;
        node.left.color = BLACK;
        node.right.color = BLACK;
    }




    public Value get(Key key){
    
    
        return get(root, key);
    }

    private Value get(Node node, Key key){
    
    
        if(null == node){
    
    
            return null;
        }

        int res = key.compareTo(node.key);

        if(res > 0){
    
    
            return get(node.right, key);
        } else if(res < 0){
    
    
            return get(node.left, key);
        } else{
    
    
            return node.value;
        }
    }



    public int size(){
    
    
        return size;
    }

}

Guess you like

Origin blog.csdn.net/Valishment/article/details/109319469