붉 은 검 은 나무 rbtree 실현, 원 액 오리지널 nginx.이 해 를 깊 게 하 라!

//rbtree.h
#ifndef _RBTREE_H_
#define _RBTREE_H_

#include <stdlib.h>
#include <stdio.h>
#include <string>

typedef unsigned int rbtree_key_t;
typedef unsigned char u_char;

typedef struct rbtree_node_s rbtree_node_t;

struct rbtree_node_s
{
    rbtree_key_t    key;
    rbtree_node_t   *left;
    rbtree_node_t   *right;
    rbtree_node_t   *parent;
    u_char            color;
    string            data;//<key,data>  
};

typedef struct rbtree_s rbtree_t;

typedef void (*rbtree_insert_pt) (rbtree_node_t *root,//    ,           
        rbtree_node_t *node, rbtree_node_t *sentinel);

struct rbtree_s
{
    rbtree_node_t    *root;
    rbtree_node_t    *sentinel;//all leaf nodes point to the sentinel node
    rbtree_insert_pt insert;
};

void rbtree_insert_value(rbtree_node_t *temp, rbtree_node_t *node,
        rbtree_node_t *sentinel);

#define rbt_red(node)            ((node)->color = 1)
#define rbt_black(node)            ((node)->color = 0)
#define rbt_is_red(node)        ((node)->color)
#define rbt_is_black(node)        (!rbt_is_red(node))
#define rbt_copy_color(n1, n2)    (n1->color = n2->color)

#define rbtree_sentinel_init(node)    rbt_black(node)

#define rbtree_init(tree, s, i)        \
    rbtree_sentinel_init(s);        \
    (tree)->root = s;                \
    (tree)->sentinel = s;            \
    (tree)->insert = i


#endif

//rbtree.cpp
#include "rbtree.h"

static inline void rbtree_left_rotate(rbtree_node_t **root, rbtree_node_t *sentinel,
        rbtree_node_t *node);/*root     */
static inline void rbtree_right_rotate(rbtree_node_t **root, rbtree_node_t *sentinel,
        rbtree_node_t *node);


void rbtree_insert_fixup(rbtree_node_t **root, rbtree_node_t *sentinel,
        rbtree_node_t *node)
{
    rbtree_node_t *temp;
    while(node != *root && rbt_is_red(node->parent))
    {
        if(node->parent == node->parent->parent->left)//left
        {
            temp = node->parent->parent->right;//   
            //case 1
            if(rbt_is_red(temp))
            {
                rbt_black(node->parent);
                rbt_black(temp);
                rbt_red(node->parent->parent);
                node = node->parent->parent;
            }
            else//black
            {
                //case 2
                if(node == node->parent->right)//RR
                {
                    node = node->parent;
                    rbtree_left_rotate(root, sentinel, node);
                }
                //case 3
                rbt_black(node->parent);
                rbt_red(node->parent->parent);
                rbtree_right_rotate(root, sentinel, node->parent->parent);
            }
        }
        else//symmetric
        {
            temp = node->parent->parent->left;//   
            //case 1
            if(rbt_is_red(temp))
            {
                rbt_black(node->parent);
                rbt_black(temp);
                rbt_red(node->parent->parent);
                node = node->parent->parent;
            }
            else//black
            {
                //case 2
                if(node == node->parent->left)//LL
                {
                    node = node->parent;
                    rbtree_right_rotate(root, sentinel, node);
                }
                //case 3
                rbt_black(node->parent);
                rbt_red(node->parent->parent);
                rbtree_left_rotate(root, sentinel, node->parent->parent);
            }

        }
    }
    rbt_black(*root);
}

void rbtree_insert(rbtree_t *tree, rbtree_node_t *node)
{
    rbtree_node_t **root, *temp, *sentinel;

    root = &tree->root;
    sentinel = tree->sentinel;

    if(*root == sentinel)
    {
        node->parent = NULL;
        node->left = sentinel;
        node->right = sentinel;
        rbt_black(node);
        *root = node;

        return;
    }

    tree->insert(*root, node, sentinel);

    /*rbtree-insert-fixup*/
    rbtree_insert_fixup(root, sentinel, node);// blance       

}

void rbtree_insert_value(rbtree_node_t *temp, rbtree_node_t *node,
        rbtree_node_t *sentinel)
{
    rbtree_node_t **p;

    //          
    for(;;)
    {
        p = (node->key < temp->key) ? &temp->left : &temp->right;

        if(*p == sentinel)
        {
            break;
        }

        temp = *p;
    }

    *p = node;//  *p             ,                  ,       ^-^
    node->parent = temp;
    node->left = sentinel;
    node->right = sentinel;
    rbt_red(node);

}

static inline void
rbtree_left_rotate(rbtree_node_t **root, rbtree_node_t *sentinel,
        rbtree_node_t *node)
{
    rbtree_node_t* tmp;
    /*
       |                       |
       x                       y
      / \                     / \
     a   y     ---left--->   x   c
        / \                 / \
       b   c               a   b
     */
    /*node = x*/
    tmp = node->right;
    node->right = tmp->left;

    //     ---3 
    if(tmp->left != sentinel)
    {
        tmp->left->parent = node;
    }

    tmp->parent = node->parent;

    if(node == *root)
    {
        *root = tmp;
    }
    else if(node == node->parent->left)
    {
        node->parent->left = tmp;
    }
    else
    {
        node->parent->right = tmp;
    }

    tmp->left = node;
    node->parent = tmp;
}

static inline void
rbtree_right_rotate(rbtree_node_t **root, rbtree_node_t *sentinel,
        rbtree_node_t *node)
{
    rbtree_node_t* tmp;
    /*
       |                       |
       x                       y
      / \                     / \
     a   y     <---right--   x   c
        / \                 / \
       b   c               a   b
     */
    /*node = y*/
    tmp = node->left;
    node->left = tmp->right;

    if(tmp->right != sentinel)
    {
        tmp->right->parent = node;
    }

    tmp->parent = node->parent;

    if(node == *root)
    {
        *root = tmp;
    }
    else if(node == node->parent->left)
    {
        node->parent->left = tmp;
    }
    else
    {
        node->parent->right = tmp;
    }

    tmp->right = node;
    node->parent = tmp;
}

좋은 웹페이지 즐겨찾기