nginx学习九 高级数据结构之红黑树ngx_rbtree_t

1红黑树简介

先来看下算法导论对R-B Tree的介绍:

红黑树,一种二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。

通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平的。

红黑树,作为一棵二叉查找树,满足二叉查找树的一般性质。下面,来了解下 二叉查找树的一般性质。

二叉查找树

二叉查找树,也称有序二叉树(ordered binary tree),或已排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树:

若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

任意节点的左、右子树也分别为二叉查找树。

没有键值相等的节点(no duplicate nodes)。

因为一棵由n个结点随机构造的二叉查找树的高度为lgn,所以顺理成章,二叉查找树的一般操作的执行时间为O(lgn)。但二叉查找树若退化成了一棵具有n个结点的线性链后,则这些操作最坏情况运行时间为O(n)。

红黑树虽然本质上是一棵二叉查找树,但它在二叉查找树的基础上增加了着色和相关的性质使得红黑树相对平衡,从而保证了红黑的查找、插入、删除的时间复杂度最坏为O(log n)。

红黑树的性质:

1) 每个结点要么是红的要么是黑的。

2) 根结点是黑的。

3) 每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的。

4) 如果一个结点是红的,那么它的两个儿子都是黑的。

5) 对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。

红黑树的主要操作:

1)查找

2)插入

3)删除

因为插入和删除会破坏红黑树的性质,所以在插入和删除之后都需要对红黑树进行调整,使其保持红黑树的性质,在调整红黑树的时候又涉及到两个基本的操作:

4)左旋

5)右旋

以上就是红黑树全部知识的简要介绍。详细讲解红黑树的文章请百度“算法之道或结构之法”或者这个链接,讲的非常详细。

下面看看nginx的红黑树是怎么实现的。

2nginx红黑树ngx_rbtree_t

2.1ngx_rbtree_t和ngx_rbtree_node_t

nginx实现的红黑树,包含两个结构体:ngx_rbtree_t和ngx_rbtree_node_t。

ngx_rbtree_t:

struct ngx_rbtree_s {
    ngx_rbtree_node_t     *root;//根节点
    ngx_rbtree_node_t     *sentinel;//设置树的哨兵节点
    ngx_rbtree_insert_pt   insert;//插入方法的函数指针
};

ngx_rbtree_node_t:

struct ngx_rbtree_node_s {
    ngx_rbtree_key_t       key;//无符号的键值
    ngx_rbtree_node_t     *left;//左子节点
    ngx_rbtree_node_t     *right;//右子节点
    ngx_rbtree_node_t     *parent;//父节点
    u_char                 color;//节点颜色,0表示黑色,1表示红色
    u_char                 data;//数据
};

可见nginx红黑树节点基本没有存储用户的数据,因为ngx_rbtree_node_t里面只有一个u_char的data,显然这个data是不能满足用户存储数据的要求的。因此,当用户使用ngx_rbtree_t时必须自己定义数据结构并申请数据空间,例如向下面这样使用:

typedef struct
{
	ngx_rbtree_node_t node;
	ngx_int_t 		  num;
	void             *data; //存储数据的指针
}TestRBTNode;//自定义的数据结构体必须包含ngx_rbtree_node_t

详细的使用请看最后的测试列子。这里不多说。

2.2常用的宏定义

下面是ngingx为实现红黑树提供的常用的宏定义操作:

//初始化红黑树
#define ngx_rbtree_init(tree, s, i)                                               ngx_rbtree_sentinel_init(s);                                                  (tree)->root = s;                                                             (tree)->sentinel = s;                                                         (tree)->insert = i

//设置节点颜色为红色
#define ngx_rbt_red(node)               ((node)->color = 1)
//设置节点颜色为黑色
#define ngx_rbt_black(node)             ((node)->color = 0)
//若节点颜色为红色返回非0,否则返回0
#define ngx_rbt_is_red(node)            ((node)->color)
//若节点颜色为黑色返回非0,否则返回0
#define ngx_rbt_is_black(node)          (!ngx_rbt_is_red(node))
//把节点2的颜色赋值给节点1
#define ngx_rbt_copy_color(n1, n2)      (n1->color = n2->color)

/* a sentinel must be black */
//初始化哨兵节点,实际设置颜色为黑色
#define ngx_rbtree_sentinel_init(node)  ngx_rbt_black(node)

2.3ngx_rbtree_insert

void ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree, ngx_rbtree_node_t *node);

向红黑树中插入节点。上面说过,向红黑树中插入节点,有可能破坏红黑树的性质,这时就需要调整红黑树,哪些情况会破坏红黑树的性质呢?下面三种情况会破坏红黑树的性质:

1)如果当前结点的父结点是红色且祖父结点的另一个子结点(叔叔结点)是红色

2)当前节点的父节点是红色,叔叔节点是黑色,当前节点是其父节点的右子

3)当前节点的父节点是红色,叔叔节点是黑色,当前节点是其父节点的左子

下面是这三种情况的对应调整方法(这里只是父节点为祖父节点的左孩子(右孩子情况类同)):

如果当前结点的父结点是红色且祖父结点的另一个子结点(叔叔结点)是红色,调整方法如下:

1)将当前节点的父节点和叔叔节点涂黑,祖父结点涂红,把当前结点指向祖父节点,从新的当前节点重新开始算法

如果当前节点的父节点是红色,叔叔节点是黑色,当前节点是其父节点的右子,调整方法如下:

2)当前节点的父节点做为新的当前节点,以新当前节点为支点左旋

如果当前节点的父节点是红色,叔叔节点是黑色,当前节点是其父节点的左子,调整方法如下:

3)父节点变为黑色,祖父节点变为红色,在祖父节点为支点右旋

看源代码:

void
ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,
    ngx_rbtree_node_t *node)
{
    ngx_rbtree_node_t  **root, *temp, *sentinel;

    /* a binary tree insert */

    root = (ngx_rbtree_node_t **) &tree->root;
    sentinel = tree->sentinel;//哨兵节点

    if (*root == sentinel) {//如果根节点为空
        node->parent = NULL;
        node->left = sentinel;
        node->right = sentinel;
        ngx_rbt_black(node);//根节点设置为黑色
        *root = node;

        return;
    }

    tree->insert(*root, node, sentinel);//插入节点

    /* re-balance tree */  /*插入调整*/

    while (node != *root && ngx_rbt_is_red(node->parent)) {//当前节点不是根节点,并且节点的父节点颜色为红色
		//父节点为祖父节点的左孩子
        if (node->parent == node->parent->parent->left) {
            temp = node->parent->parent->right;//取叔叔节点
            //情况1:父节点为红,叔叔节点为红
            if (ngx_rbt_is_red(temp)) {//解决方法:
                ngx_rbt_black(node->parent);//父节点修改为黑色
                ngx_rbt_black(temp);        //叔叔节点改为黑色
                ngx_rbt_red(node->parent->parent);//祖父节点修改为红色
                node = node->parent->parent;//修改祖父节点为当前节点,重新开始算法

            } else {//情况2:父节点为红,叔叔节点为黑色,当前节点为父节点的右孩子
                if (node == node->parent->right) {//解决方法:
                    node = node->parent;//修改当前节点为父节点
                    ngx_rbtree_left_rotate(root, sentinel, node);//左旋当前节点
                }
                //情况3:父节点为红,叔叔节点为黑色,当前节点为父节点的左孩子
                ngx_rbt_black(node->parent);//解决方法:父节点修改为黑色
                ngx_rbt_red(node->parent->parent);//祖父节点修改为红色
                ngx_rbtree_right_rotate(root, sentinel, node->parent->parent);//右旋祖父节点
            }

        } else {//父节点为祖父节点的右孩子,这也有三种情况,和上述情况操作类似,只不过旋转方向相反
            temp = node->parent->parent->left;

            if (ngx_rbt_is_red(temp)) {
                ngx_rbt_black(node->parent);
                ngx_rbt_black(temp);
                ngx_rbt_red(node->parent->parent);
                node = node->parent->parent;

            } else {
                if (node == node->parent->left) {
                    node = node->parent;
                    ngx_rbtree_right_rotate(root, sentinel, node);
                }

                ngx_rbt_black(node->parent);
                ngx_rbt_red(node->parent->parent);
                ngx_rbtree_left_rotate(root, sentinel, node->parent->parent);
            }
        }
    }

    ngx_rbt_black(*root);//根节点永远是黑色
}

插入的情况要比删除的情况简单的多!

2.4ngx_rbtree_delete

void ngx_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)。

在红黑树中删除节点,删除节点也有可能破坏红黑树的性质,需要调整红黑树。下面四种删除操作会破坏红黑树的性质:

1)当前节点是黑+黑且兄弟节点为红色(此时父节点和兄弟节点的子节点分为黑)

2)当前节点是黑加黑且兄弟是黑色且兄弟节点的两个子节点全为黑色

3)当前节点颜色是黑+黑,兄弟节点是黑色,兄弟的左子是红色,右子是黑色

4)当前节点颜色是黑-黑色,它的兄弟节点是黑色,但是兄弟节点的右子是红色,兄弟节点左子的颜色任意

下面是这四种情况对应的调整方法:

如果当前节点是黑+黑且兄弟节点为红色(此时父节点和兄弟节点的子节点分为黑),调整如下:

1)把父节点染成红色,把兄弟结点染成黑色,左旋父节点

如果当前节点是黑加黑且兄弟是黑色且兄弟节点的两个子节点全为黑色,调整如下:

2)把当前节点和兄弟节点中抽取一重黑色追加到父节点上,把父节点当成新的当前节点

如果当前节点颜色是黑+黑,兄弟节点是黑色,兄弟的左子是红色,右子是黑色,调整如下:

3)把兄弟结点染红,兄弟左子节点染黑,之后再在兄弟节点为支点解右旋

如果当前节点颜色是黑-黑色,它的兄弟节点是黑色,但是兄弟节点的右子是红色,兄弟节点左子的颜色任意,调整如下:

4)把兄弟节点染成当前节点父节点的颜色,把当前节点父节点染成黑色,兄弟节点右子染成黑色,之后以当前节点的父节点为支点进行左旋。

源代码:

void
ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,
    ngx_rbtree_node_t *node)
{
    ngx_uint_t           red;
    ngx_rbtree_node_t  **root, *sentinel, *subst, *temp, *w;

    /* a binary tree delete */

    root = (ngx_rbtree_node_t **) &tree->root;
    sentinel = tree->sentinel;//哨兵节点

    if (node->left == sentinel) {//左子节点为空
        temp = node->right;
        subst = node;//subst记录后继节点,用着个节点代替删除节点

    } else if (node->right == sentinel) {//右子节点为空
        temp = node->left;
        subst = node;

    } else {//左右子节点都不为空
        subst = ngx_rbtree_min(node->right, sentinel);//右子树中最小的节点

        if (subst->left != sentinel) {
            temp = subst->left;
        } else {
            temp = subst->right;
        }
    }

    if (subst == *root) {//根节点的情况
        *root = temp;
        ngx_rbt_black(temp);

        /* DEBUG stuff */
        node->left = NULL;
        node->right = NULL;
        node->parent = NULL;
        node->key = 0;

        return;
    }

    red = ngx_rbt_is_red(subst);//如果后继是红色,就不需要调整红黑树
                                //因为实际上删除的是后继节点
    /*下面是一些指针的修改,不详细介绍,参看二叉排序树的删除*/
    if (subst == subst->parent->left) {
        subst->parent->left = temp;

    } else {
        subst->parent->right = temp;
    }

    if (subst == node) {

        temp->parent = subst->parent;

    } else {

        if (subst->parent == node) {
            temp->parent = subst;

        } else {
            temp->parent = subst->parent;
        }

        subst->left = node->left;
        subst->right = node->right;
        subst->parent = node->parent;
        ngx_rbt_copy_color(subst, node);

        if (node == *root) {
            *root = subst;

        } else {
            if (node == node->parent->left) {
                node->parent->left = subst;
            } else {
                node->parent->right = subst;
            }
        }

        if (subst->left != sentinel) {
            subst->left->parent = subst;
        }

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

    /* DEBUG stuff */
    node->left = NULL;
    node->right = NULL;
    node->parent = NULL;
    node->key = 0;

    if (red) {//
        return;
    }

    /* a delete fixup *///调整红黑树的四种情况,看注释

    while (temp != *root && ngx_rbt_is_black(temp)) {
        //当前节点为左节点的情况
        if (temp == temp->parent->left) {
            w = temp->parent->right;
            //情况1:当前节点为黑色,兄弟节点为红色
            if (ngx_rbt_is_red(w)) {
                ngx_rbt_black(w);//解决: 兄弟节点修改为黑色
                ngx_rbt_red(temp->parent);//父节点修改红色
                ngx_rbtree_left_rotate(root, sentinel, temp->parent);//左旋父节点
                w = temp->parent->right;
            }
            //情况2:当前节点为黑色,兄弟节点为黑色,兄弟节点的俩子节点也为黑色
            if (ngx_rbt_is_black(w->left) && ngx_rbt_is_black(w->right)) {
                ngx_rbt_red(w);//解决:兄弟节点修改为红色
                temp = temp->parent;//当前节点指向父节点

            } else {//情况3:当前节点为黑色,兄弟节点为黑色,兄弟节点右子节点为黑色,左子节点为红色
                if (ngx_rbt_is_black(w->right)) {
                    ngx_rbt_black(w->left);//解决:左子节点改为黑色
                    ngx_rbt_red(w);//兄弟节点改为红色
                    ngx_rbtree_right_rotate(root, sentinel, w);//右旋兄弟节点
                    w = temp->parent->right;
                }
                //情况4:当前节点为黑色,兄弟节点为黑色,兄弟节点右子节点为红色,左子节点任意色
                ngx_rbt_copy_color(w, temp->parent);//解决:兄弟节点修改为父节点的颜色
                ngx_rbt_black(temp->parent);        //父节点修给为黑色
                ngx_rbt_black(w->right);            //右子节点修改为黑色
                ngx_rbtree_left_rotate(root, sentinel, temp->parent);//左旋父节点
                temp = *root;
            }

        } else {//当前节点为右节点的情况
            w = temp->parent->left;

            if (ngx_rbt_is_red(w)) {
                ngx_rbt_black(w);
                ngx_rbt_red(temp->parent);
                ngx_rbtree_right_rotate(root, sentinel, temp->parent);
                w = temp->parent->left;
            }

            if (ngx_rbt_is_black(w->left) && ngx_rbt_is_black(w->right)) {
                ngx_rbt_red(w);
                temp = temp->parent;

            } else {
                if (ngx_rbt_is_black(w->left)) {
                    ngx_rbt_black(w->right);
                    ngx_rbt_red(w);
                    ngx_rbtree_left_rotate(root, sentinel, w);
                    w = temp->parent->left;
                }

                ngx_rbt_copy_color(w, temp->parent);
                ngx_rbt_black(temp->parent);
                ngx_rbt_black(w->left);
                ngx_rbtree_right_rotate(root, sentinel, temp->parent);
                temp = *root;
            }
        }
    }

    ngx_rbt_black(temp);
}

2.5左旋和右旋,查找节点

左旋和右旋操作非常简单,这里就不介绍了,查找操作nginx没有实现,我们可以根据二叉排序树来实现一个查找函数,这里也不介绍。

http://blog.csdn.net/xiaoliangsky/article/details/39803589

3测试红黑树的例子

测试代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <ngx_core.h>
#include <ngx_config.h>
#include <ngx_conf_file.h>
#include <ngx_string.h>
#include <ngx_palloc.h>
#include <ngx_rbtree.h>

#define ngx_rbtee_data(p, type, member) (type*)((u_char*)p - offset(type, member))

//节点数据结构
typedef struct
{
    ngx_rbtree_node_t  node;//方便类型转化
    ngx_str_t          str;
}ngx_string_node_t;

//自定义插入函数
void ngx_string_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
    ngx_rbtree_node_t *sentinel);

//先序遍历红黑树
void trave_rbtree(ngx_rbtree_node_t *root, ngx_rbtree_node_t *sentinel);

int main()
{
    ngx_rbtree_t      tree;
    ngx_rbtree_node_t sentinel;

    ngx_rbtree_init(&tree, &sentinel, ngx_string_rbtree_insert_value);

    ngx_string_node_t strNode[10];

    ngx_str_set(&strNode[0].str, "abc0");
    strNode[0].node.key = 1;

    ngx_str_set(&strNode[1].str, "abc1");
    strNode[1].node.key = 6;

    ngx_str_set(&strNode[2].str, "abc2");
    strNode[2].node.key = 8;

	ngx_str_set(&strNode[3].str, "abc35");
    strNode[3].node.key = 11;

	ngx_str_set(&strNode[4].str, "abd4");
    strNode[4].node.key = 8;

	ngx_str_set(&strNode[5].str, "abc5");
    strNode[5].node.key = 1;

    ngx_str_set(&strNode[6].str, "abc11");
    strNode[6].node.key = 11;

	ngx_str_set(&strNode[7].str, "a6");
    strNode[7].node.key = 1;

	ngx_str_set(&strNode[8].str, "a8");
    strNode[8].node.key = 6;

    ngx_str_set(&strNode[9].str, "abc0");
    strNode[9].node.key = 6;

	ngx_int_t i;
	for (i = 0; i < 10; ++i)
	{
		ngx_rbtree_insert(&tree, &strNode[i].node);
	}

    travel_rbtree(tree.root, tree.sentinel);

    return 0;
}

void
ngx_string_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
    ngx_rbtree_node_t *sentinel)
{
    ngx_rbtree_node_t  **p;
    ngx_string_node_t      *strNodeX;
    ngx_string_node_t      *strNodeY;

    for ( ;; )
    {
        if (node->key != temp->key)
        {
             p = (node->key < temp->key) ? &temp->left : &temp->right;
        }
        else
        {
            strNodeX = (ngx_string_node_t*)node;//类型转化,因为node的地址和ngx_string_node_t的地址相同
            //strNodeY = (ngx_string_node_t*)temp;
            //或者这样用
			strNodeY = ngx_rbtree_data(temp, ngx_string_node_t, node);

            if (strNodeX->str.len != strNodeY->str.len)
            {
                p = (strNodeX->str.len < strNodeY->str.len) ? &temp->left : &temp->right;
            }
            else
            {
                p = (ngx_memcmp(strNodeX->str.data, strNodeY->str.data, strNodeX->str.len) < 0) ? &temp->left : &temp->right;
            }
        }

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

        temp = *p;
    }
	//每一个待插入的节点必须初始化为红色
    *p = node;
    node->parent = temp;//初始化父节点
    node->left = sentinel;//初始化左子节点
    node->right = sentinel;//初始化右子节点
    ngx_rbt_red(node);//颜色设置为红色
}

void
travel_rbtree(ngx_rbtree_node_t* root, ngx_rbtree_node_t *sentinel)
{
	if (root->left != sentinel)
	{
		travel_rbtree(root->left, sentinel);
	}

	ngx_string_node_t* strNode = (ngx_string_node_t*)root;
	printf("key = %d , str=%s\n", root->key, strNode->str.data);

	if (root->right != sentinel)
	{
		travel_rbtree(root->right, sentinel);
	}
}

makefile:

gcc -c -g -Wall -Wextra -I. -I /home/wyp/桌面/testkNx/nginx-1.0.15/src/core -I /home/wyp/桌面/testkNx/nginx-1.0.15/src/event -I /home/wyp/桌面/testkNx/nginx-1.0.15/src/event/modules -I /home/wyp/桌面/testkNx/nginx-1.0.15/src/os/unix -I /home/wyp/桌面/testkNx/nginx-1.0.15/objs  /home/wyp/桌面/testkNx/nginx-1.0.15/objs/src/core/ngx_rbtree.o ngx_rbtree.c
时间: 2024-10-06 05:47:44

nginx学习九 高级数据结构之红黑树ngx_rbtree_t的相关文章

nginx学习六 高级数据结构之双向链表ngx_queue_t

1 ngx_queue_t简介 ngx_queue_t是nginx提供的一个轻量级的双向链表容器,它不负责存储数据,既不提供数据的内存分配,它只有两个指针负责把数据链入链表,它跟stl提供的queue不同,stl提供的queue帮助用户存储数据,用户只需要相容器里添加数据即可,而ngx_queue_t,用户必须自己提供存储数据的内存,并且必须定义一种数据结构把ngx_queue_t包含在其中,然后利用ngx_queue_t提供的函数来进行相应的操作. 2 ngx_queue_t结构及其操作 2.

nginx学习七 高级数据结构之动态数组ngx_array_t

1 ngx_array_t结构 ngx_array_t是nginx内部使用的数组结构.nginx的数组结构在存储上与大家认知的C语言内置的数组有相似性,比如实际上存储数据的区域也是一大块连续的内存.但是数组除了存储数据的内存以外还包含一些元信息来描述相关的一些信息,并且可以动态增长.下面 我们从数组的定义上来详细的了解一下.ngx_array_t的定义位于src/core/ngx_array.c|h里面. struct ngx_array_s { void *elts;//数组的首地址 ngx_

nginx 学习八 高级数据结构之基数树ngx_radix_tree_t

1 nginx的基数树简介 基数树是一种二叉查找树,它具备二叉查找树的所有优点:检索.插入.删除节点速度快,支持范围查找,支持遍历等.在nginx中仅geo模块使用了基数树.nginx的基数树使用ngx_radix_tree_t这个结构体表示的.ngx_radix_tree_t要求存储的每个节点都必须以32位整形作为区别任意两个节点的唯一标识.ngx_radix_tree_t基数树会负责分配每个节点占用的内存,基数树的每个节点中可存储的值只是一个指针,这个指针指向实际的数据. 节点结构ngx_r

菜鸟nginx源码剖析数据结构篇(四)红黑树ngx_rbtree_t[转]

菜鸟nginx源码剖析数据结构篇(四)红黑树ngx_rbtree_t Author:Echo Chen(陈斌) Email:[email protected] Blog:Blog.csdn.net/chen19870707 Date:October 27h, 2014 1.ngx_rbtree优势和特点 ngx_rbtree是一种使用红黑树实现的关联容器,关于红黑树的特性,在<手把手实现红黑树>已经详细介绍,这里就只探讨ngx_rbtree与众不同的地方:ngx_rbtree红黑树容器中的元素

D&amp;F学数据结构系列——红黑树

红黑树 定义:一棵二叉查找树如果满足下面的红黑性质,则为一棵红黑树: 1)每个结点不是红的就是黑的 2)根结点是黑的 3)每个叶结点是黑的 4)如果一个结点是红的,它的两个儿子都是黑的(即不可能有两个连续的红色结点) 5)对于每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点 性质: 这些约束确保了红黑树的关键特性: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长.结果是这个树大致上是平衡的.因为操作比如插入.删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上

菜鸟nginx源码剖析数据结构篇(四)红黑树ngx_rbtree_t

Author:Echo Chen(陈斌) Email:[email protected] Blog:Blog.csdn.net/chen19870707 Date:October 27h, 2014 1.ngx_rbtree优势和特点 ngx_rbtree是一种使用红黑树实现的关联容器,关于红黑树的特性,在<手把手实现红黑树>已经详细介绍,这里就只探讨ngx_rbtree与众不同的地方:ngx_rbtree红黑树容器中的元素都是有序的,支持快速索引,插入,删除操作,也支持范围查询,遍历操作,应

数据结构之红黑树

红黑树(Red Black Tree) 是一种自平衡二叉查找树 红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能.它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目.(度娘)C++ stl里面的set,map底层就是用红黑树实现的.红黑树具体的插入删除原理请参考<<算法导论>> 维基上面也讲得不错.反正插入过程就是要解决&q

【算法导论】学习笔记——第13章 红黑树

红黑树(red-black tree)是许多平衡搜索树中的一种,因此基本操作(查询.删除.搜索)等在最坏情况下的时间复杂度均为O(lgn).13. 1 红黑树的性质红黑树时一棵二叉搜索树,并且在每个结点上增加了一个属性表示颜色:红色或黑色.通过对任何一条从根到叶子的简单路径上各个结点的颜色进行约束,红黑树确保没有一条路径会比其它路径长出2倍.因而是近似于平衡的.一棵红黑树是满足下面红黑性质的二叉搜索树:1. 每个结点是红色或黑色:2. 根结点是黑色的:3. 每个叶结点(NIL)是黑色的:4. 如

数据结构:红黑树解析

本文参考:Google.算法导论.STL源码剖析.计算机程序设计艺术. 推荐阅读: Left-Leaning Red-Black Trees, Dagstuhl Workshop on Data Structures, Wadern, Germany, February, 2008,直接下载:http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf. 本文的github优化版:https://github.com/julycoding/The