Data structure and algorithm: 1. Red-black tree can be seen everywhere

1. What is a red-black tree

  1. Red-black tree is a specific type of binary tree, a structure used to organize data
  2. The red-black tree is a variant of a balanced binary search tree. The height difference between the left and right subtrees may be greater than 1. It is not a balanced binary tree (AVL) in the strict sense.
  3. When searching the red-black tree, the search algorithm on the ordinary binary sorting tree can be used, and the color information is not required in the search process

2. Where is the red-black tree used?

  1. hashmap
  2. cfs
  3. epoll
  4. timer
  5. nginx

Main usage:

  1. Find the value by key
  2. Binary sorting tree, there is an order, and it is executed as a sequence

Because key-value is a strong search process, the kv structure has the following types

  1. rbtree
  2. hash
  3. b/b+tree
  4. jump table

3. Red-black tree properties

  1. Each node is red or black
  2. root node is black
  3. Each leaf node is black
  4. If a node is red, both of its children are black
  5. For each node, from the node to its descendant nodes to all paths contain the same number of black nodes (determined the same height)
#define RBTREE_ENTRY(name, type)    \
    struct name {
      
                         \
        struct type *right; \
        struct type *left;  \
        struct type *parent;\
        unsigned char color;        \
    }

typedef struct _rbtree_node{
    
    

    KEY_TYPE key;
    void *value;
#if 1
    struct _rbtree_node *right;
    struct _rbtree_node *left;
    struct _rbtree_node *parent;
    unsigned char color;
#else

    RBTREE_ENTRY(, rb_node) node; // 把红黑树的性质封装一下, 会更灵活

#endif
} rbtree_node;

typedef struct _rbtree {
    
    

    struct _rbtree_node *root;
    struct _rbtree_node *nil;

} rbtree;

4. Rotate

  1. Only when the nature of the red-black tree is destroyed, it is adjusted
  2. The maximum number of rotations of a red-black tree is the layer height
  3. Rotation is to not affect other nodes, better to change color
// 左旋:要一个树, 和一个待旋转的结点
// 1. x指向y的左子树
// 2. y的左子树指向x
// 3. x的parent指向y
// 改变方向, 总共需要改动6个指针
void rbtree_left_rotate(rbtree *T, rbtree_node *x){
    
    
    rbtree_node *y = x->right;
    // 1. x指向y的左子树
    x->right = y->left;
    // 如果不是叶子结点, 才进行修改
    if(y->left != T->nil){
    
    
        y->left->parent = x;
    }
    // 2. y的左子树指向x
    y->parent = x->parent;
    // 需要判断一下x是不是根结点
    if(x->parent == T->nil){
    
    
        T->root = y;
    }else if(x == x->parent->left){
    
    
        x->parent->left = y;
    }else{
    
    
        x->parent->right = y;
    }

    // 3. x的parent指向y
    y->left = x;
    x->parent = y;
}

void rbtree_right_rotate(rbtree *T, rbtree_node *y){
    
    
     rbtree_node *x = y->left;
    // 1. 
    y->left = x->right;
    // 如果不是叶子结点, 才进行修改
    if(x->right != T->nil){
    
    
        x->right->parent = y;
    }
    // 2. 
    x->parent = y->parent;
    // 需要判断一下y是不是根结点
    if(y->parent == T->nil){
    
    
        T->root = x;
    }else if(y == y->parent->right){
    
    
        y->parent->right = x;
    }else{
    
    
        y->parent->left = x;
    }

    x->right = y;
    y->parent = x;
}

5. Color

Before a red-black tree is inserted into any node, he is already a red-black tree

  1. On red, the height of this black has not been modified
    1. If the parent node is red, you need to adjust
    2. If the uncle node is red
    3. If the uncle node is black and the current node is the left child
      1. At this time, you need to turn right, because the left side is heavier
      2. Change the parent node to black, the grandparent node to red, and rotate
void rbtree_insert_fixup(rbtree *T, rbtree_node *z){
    
    
    // z->color == RED
    while(z->parent->color == RED){
    
    
        // 不清楚父节点是左子树还是右子树
        if(z->parent == z->parent->parent->left){
    
    
            rbtree_node *y = z->parent->parent->right;
            if(y->color == RED){
    
    
                z->parent->color = BLACK;
                y->color = BLACK;
                z->parent->parent->color = RED;
                z = z->parent->parent; // z在每一次循环回溯的时候,都是红色的
            }else{
    
     // y->color == BLACK
                if(z == z->parent->right){
    
    
                    z = z->parent;
                    rbtree_left_rotate(T, z);
                }
                z->parent->color = BLACK;
                z->parent->parent->color = RED;
                rbtree_right_rotate(T, z->parent->parent);
            }
        }
    }
}

void rbtree_insert(rbtree *T, rbtree_node *z){
    
    
    rbtree_node *x = T->root;
    rbtree_node *y = T->nil;
    while(x != T->nil){
    
    
        y = x;
        if(z->key < x->key){
    
    
            x = x->left;
        }else if(z->key > x->key){
    
    
            x = x->right;
        }else{
    
     // Exist
            return;
        }
    }
    // 如果这个红黑树一个结点都没有
    if(y == T->nil){
    
    
        T->root = z;
    }else{
    
    
        // z 插到 y 的左子树还是右子树 ?
        if(y->key > z->key){
    
    
            y->left = z;
        }else{
    
    
            y->right = z;
        }
    }
    z->parent = y;
    z->left = T->nil;
    z->right = T->nil;
    z->color = RED;
}

Recommend a free open course of Zero Sound Academy. I personally think the teacher taught it well, so I would like to share it with you:

Linux, Nginx, ZeroMQ, MySQL, Redis, fastdfs, MongoDB, ZK, streaming media, CDN, P2P, K8S, Docker, TCP/IP, coroutines, DPDK and other technical content, learn now

Guess you like

Origin blog.csdn.net/weixin_44839362/article/details/128995382