红黑树的实现源码

最近因为要给ccache加入红黑树的支持, 找出来曾经实现的代码作为参考, 这才发现原来 的实现都是有问题的,也怪我的测试用例写的不好, 仅仅对插入操作进行了测试, 我向所有因 为阅读了这份代码而造成困惑的朋友表示道歉.

这次重新实现, 所有的代码推倒重新编写, 参考了linux内核中红黑树的实现算法, 并且 对测试用例进行了加强,希望这是最后一个对红黑树算法的修订版本.

/*-----------------------------------------------------------    RB-Tree的插入和删除操作的实现算法    参考资料:    1) <<Introduction to algorithm>>    2) http://lxr.linux.no/linux/lib/rbtree.c    作者:http://www.cppblog.com/converse/    您可以自由的传播,修改这份代码,转载处请注明原作者    红黑树的几个性质:    1) 每个结点只有红和黑两种颜色    2) 根结点是黑色的    3)空节点是黑色的(红黑树中,根节点的parent以及所有叶节点lchild、rchild都不指向NULL,而是指向一个定义好的空节点)。     4) 如果一个结点是红色的,那么它的左右两个子结点的颜色是黑色的    5) 对于每个结点而言,从这个结点到叶子结点的任何路径上的黑色结点    的数目相同-------------------------------------------------------------*/#include <stdio.h>#include <stdlib.h>#include <string.h>typedef int key_t;typedef int data_t;typedef enum color_t{    RED = 0,    BLACK = 1}color_t;typedef struct rb_node_t{    struct rb_node_t *left, *right, *parent;    key_t key;    data_t data;    color_t color;}rb_node_t;/* forward declaration */rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root);rb_node_t* rb_search(key_t key, rb_node_t* root);rb_node_t* rb_erase(key_t key, rb_node_t* root);int main(){    int i, count = 900000;    key_t key;    rb_node_t* root = NULL, *node = NULL;    srand(time(NULL));    for (i = 1; i < count; ++i)    {        key = rand() % count;        if ((root = rb_insert(key, i, root)))        {            printf("[i = %d] insert key %d success!\n", i, key);        }        else        {            printf("[i = %d] insert key %d error!\n", i, key);            exit(-1);        }        if ((node = rb_search(key, root)))        {            printf("[i = %d] search key %d success!\n", i, key);        }        else        {            printf("[i = %d] search key %d error!\n", i, key);            exit(-1);        }        if (!(i % 10))        {            if ((root = rb_erase(key, root)))            {                printf("[i = %d] erase key %d success\n", i, key);            }            else            {                printf("[i = %d] erase key %d error\n", i, key);            }        }    }    return 0;}static rb_node_t* rb_new_node(key_t key, data_t data){    rb_node_t *node = (rb_node_t*)malloc(sizeof(struct rb_node_t));    if (!node)    {        printf("malloc error!\n");        exit(-1);    }    node->key = key, node->data = data;    return node;}/*-----------------------------------------------------------|   node           right|   / \    ==>     / \|   a  right     node  y|       / \           / \|       b  y         a   b -----------------------------------------------------------*/static rb_node_t* rb_rotate_left(rb_node_t* node, rb_node_t* root){    rb_node_t* right = node->right;    if ((node->right = right->left))    {        right->left->parent = node;    }    right->left = node;    if ((right->parent = node->parent))    {        if (node == node->parent->right)        {            node->parent->right = right;        }        else        {            node->parent->left = right;        }    }    else    {        root = right;    }    node->parent = right;    return root;}/*-----------------------------------------------------------|       node           left|       / \            / \|    left  y   ==>    a   node|   / \               / \|  a   b             b   y-----------------------------------------------------------*/static rb_node_t* rb_rotate_right(rb_node_t* node, rb_node_t* root){    rb_node_t* left = node->left;    if ((node->left = left->right))    {        left->right->parent = node;    }    left->right = node;    if ((left->parent = node->parent))    {        if (node == node->parent->right)        {            node->parent->right = left;        }        else        {            node->parent->left = left;        }    }    else    {        root = left;    }    node->parent = left;    return root;}static rb_node_t* rb_insert_rebalance(rb_node_t *node, rb_node_t *root){    rb_node_t *parent, *gparent, *uncle, *tmp;    while ((parent = node->parent) && parent->color == RED)    {        gparent = parent->parent;        if (parent == gparent->left)        {            uncle = gparent->right;            if (uncle && uncle->color == RED)            {                uncle->color = BLACK;                parent->color = BLACK;                gparent->color = RED;                node = gparent;            }            else            {                if (parent->right == node)                {                    root = rb_rotate_left(parent, root);                    tmp = parent;                    parent = node;                    node = tmp;                }                parent->color = BLACK;                gparent->color = RED;                root = rb_rotate_right(gparent, root);            }        }         else         {            uncle = gparent->left;            if (uncle && uncle->color == RED)            {                uncle->color = BLACK;                parent->color = BLACK;                gparent->color = RED;                node = gparent;            }            else            {                if (parent->left == node)                {                    root = rb_rotate_right(parent, root);                    tmp = parent;                    parent = node;                    node = tmp;                }                parent->color = BLACK;                gparent->color = RED;                root = rb_rotate_left(gparent, root);            }        }    }    root->color = BLACK;    return root;}static rb_node_t* rb_erase_rebalance(rb_node_t *node, rb_node_t *parent, rb_node_t *root){    rb_node_t *other, *o_left, *o_right;    while ((!node || node->color == BLACK) && node != root)    {        if (parent->left == node)        {            other = parent->right;            if (other->color == RED)            {                other->color = BLACK;                parent->color = RED;                root = rb_rotate_left(parent, root);                other = parent->right;            }            if ((!other->left || other->left->color == BLACK) &&                (!other->right || other->right->color == BLACK))            {                other->color = RED;                node = parent;                parent = node->parent;            }            else            {                if (!other->right || other->right->color == BLACK)                {                    if ((o_left = other->left))                    {                        o_left->color = BLACK;                    }                    other->color = RED;                    root = rb_rotate_right(other, root);                    other = parent->right;                }                other->color = parent->color;                parent->color = BLACK;                if (other->right)                {                    other->right->color = BLACK;                }                root = rb_rotate_left(parent, root);                node = root;                break;            }        }        else        {            other = parent->left;            if (other->color == RED)            {                other->color = BLACK;                parent->color = RED;                root = rb_rotate_right(parent, root);                other = parent->left;            }            if ((!other->left || other->left->color == BLACK) &&                (!other->right || other->right->color == BLACK))            {                other->color = RED;                node = parent;                parent = node->parent;            }            else            {                if (!other->left || other->left->color == BLACK)                {                    if ((o_right = other->right))                    {                        o_right->color = BLACK;                    }                    other->color = RED;                    root = rb_rotate_left(other, root);                    other = parent->left;                }                other->color = parent->color;                parent->color = BLACK;                if (other->left)                {                    other->left->color = BLACK;                }                root = rb_rotate_right(parent, root);                node = root;                break;            }        }    }    if (node)    {        node->color = BLACK;    }     return root;}static rb_node_t* rb_search_auxiliary(key_t key, rb_node_t* root, rb_node_t** save){    rb_node_t *node = root, *parent = NULL;    int ret;    while (node)    {        parent = node;        ret = node->key - key;        if (0 < ret)        {            node = node->left;        }        else if (0 > ret)        {            node = node->right;        }        else        {            return node;        }    }    if (save)    {        *save = parent;    }    return NULL;}rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root){    rb_node_t *parent = NULL, *node;    parent = NULL;    if ((node = rb_search_auxiliary(key, root, &parent)))    {        return root;    }    node = rb_new_node(key, data);    node->parent = parent;     node->left = node->right = NULL;    node->color = RED;    if (parent)    {        if (parent->key > key)        {            parent->left = node;        }        else        {            parent->right = node;        }    }    else    {        root = node;    }    return rb_insert_rebalance(node, root);}rb_node_t* rb_search(key_t key, rb_node_t* root){    return rb_search_auxiliary(key, root, NULL);}rb_node_t* rb_erase(key_t key, rb_node_t *root){    rb_node_t *child, *parent, *old, *left, *node;    color_t color;    if (!(node = rb_search_auxiliary(key, root, NULL)))    {        printf("key %d is not exist!\n");        return root;    }    old = node;    if (node->left && node->right)    {        node = node->right;        while ((left = node->left) != NULL)        {            node = left;        }        child = node->right;        parent = node->parent;        color = node->color;        if (child)        {            child->parent = parent;        }        if (parent)        {            if (parent->left == node)            {                parent->left = child;            }            else            {                parent->right = child;            }        }        else        {            root = child;        }        if (node->parent == old)        {            parent = node;        }        node->parent = old->parent;        node->color = old->color;        node->right = old->right;        node->left = old->left;        if (old->parent)        {            if (old->parent->left == old)            {                old->parent->left = node;            }            else            {                old->parent->right = node;            }        }         else        {            root = node;        }        old->left->parent = node;        if (old->right)        {            old->right->parent = node;        }    }    else    {        if (!node->left)        {            child = node->right;        }        else if (!node->right)        {            child = node->left;        }        parent = node->parent;        color = node->color;        if (child)        {            child->parent = parent;        }        if (parent)        {            if (parent->left == node)            {                parent->left = child;            }            else            {                parent->right = child;            }        }        else        {            root = child;        }    }    free(old);    if (color == BLACK)    {        root = rb_erase_rebalance(child, parent, root);    }    return root;}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索color
, node
, root
, nodes
, black
, node jsheaders
, node jswebstormconcurrenterror
, #parent
, left
, linux内核红黑树
, right
, parent
, parents
parent()
红黑树源码、红黑树的实现、红黑树实现、红黑树java实现、红黑树c语言实现,以便于您获取更多的相关知识。

时间: 2024-10-31 16:24:16

红黑树的实现源码的相关文章

一步一图一代码,一定要让你真正彻底明白红黑树【转】

转自:http://blog.csdn.net/chenhuajie123/article/details/11951777 一步一图一代码,一定要让你真正彻底明白红黑树   作者:July   二零一一年一月九日 ----------------------------- 本文参考:I.  The Art of Computer Programming Volume III. Introduction to Algorithms, Second EditionIII.The Annotated

c++-侯捷stl源码剖析红黑树代码问题

问题描述 侯捷stl源码剖析红黑树代码问题 在侯捷的stl源码剖析这本书中,P218,红黑树的数据结构代码中有这样一行代码: typedef simple_alloc rb_tree_node_allocator; ,在编译时会报错,其错误为: error: 'simple_alloc' does not name a type 一直没查找到答案,不知道该怎么修改,还请高手解答

Java集合源码剖析:TreeMap源码剖析

前言 本文不打算延续前几篇的风格(对所有的源码加入注释),因为要理解透TreeMap的所有源码,对博主来说,确实需要耗费大量的时间和经历,目前看来不大可能有这么多时间的投入,故这里意在通过于阅读源码对TreeMap有个宏观上的把握,并就其中一些方法的实现做比较深入的分析. 红黑树简介 TreeMap是基于红黑树实现的,这里只对红黑树做个简单的介绍,红黑树是一种特殊的二叉排序树,关于二叉排序树,参见:http://blog.csdn.net/ns_code/article/details/1982

Java集合学习(十二) TreeMap详细介绍(源码解析)和使用示例

这一章,我们对TreeMap进行学习. 第1部分 TreeMap介绍 TreeMap 简介 TreeMap 是一个有序的key-value集合,它是通过红黑树实现的. TreeMap继承于AbstractMap,所以它是一个Map,即一个key-value集合. TreeMap 实现了NavigableMap接口,意味着它支持一系列的导航方法.比如返回有序的key集合. TreeMap 实现了Cloneable接口,意味着它能被克隆. TreeMap 实现了java.io.Serializabl

MySQL源码:Range优化相关的数据结构

1. 背景知识 在开始介绍Range的主要数据结构之前,我们先看Range优化的一些概念和背景.依旧建议先阅读参考文件的[1-8],Sergey Petrunya写的PPT和文档质量都很高,很多图示,非常直观的展示了原理. (1) 什么是Range条件? 参考Range Optimization@MySQL Manual 单列Range和多列Range (2) 给定一个KEY(key1)对应的WHERE条件,如何将其转化成一个Range,下面是"简述",详细参考单列Range: SEL

java源码阅读方法以及经验

问题描述 java源码阅读方法以及经验 如何更好的阅读java源码,更注重阅读哪些包里面的源码,当然连好的阅读源码的工具也说明一下更好了 解决方案 我在这里假设你在问怎么阅读jdk的源码,java源码这个名字有点奇怪. 你可以build 一个fast debug版本,然后使用debugger去调试你的程序,这样对程序是怎么调用的有很直观的视图. 其次,可以看看jdk里面的regression tests,里面有很多例子. 其次,openjdk提供了netbean的jdk project,你可以很

红黑树的插入

一.红黑树的介绍 先来看下算法导论对R-B Tree的介绍: 红黑树,一种二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black. 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其 他路径长出俩倍,因而是接近平衡的. 前面说了,红黑树,是一种二叉查找树,既然是二叉查找树,那么它必满足二叉查找树的一般性质. 下面,在具体介绍红黑树之前,咱们先来了解下 二叉查找树的一般性质: 1.在一棵二叉查找树上,执行查找.插入.删除等操作,的时间复杂

HashMap源码分析(jdk1.8)

HashMap源码前前后后看了好几次,也和同事分享过好几次,每次都有新的收获. 分享也是一种提高! 本文首写于个人云笔记(点击访问),经多次修改,短期内不会有重大修改了,现发于此,有任何问题欢迎交流指正.     本文最初借鉴于http://www.cnblogs.com/hzmark/archive/2012/12/24/HashMap.html,其基于jdk1.6,自己分析jdk1.8后,发现有很大的不同,遂记录于此.     Java最基本的数据结构有数组和链表.数组的特点是空间连续(大小

数据结构和算法05 之红-黑树(看完包懂~)

(友情提示,红-黑树是基于二叉搜索树的,如果对二叉搜索树不了解,可以先看看:二叉搜索树 )                从第4节的分析中可以看出,二叉搜索树是个很好的数据结构,可以快速地找到一个给定关键字的数据项,并且可以快速地插入和删除数据项.但是二叉搜索树有个很麻烦的问题,如果树中插入的是随机数据,则执行效果很好,但如果插入的是有序或者逆序的数据,那么二叉搜索树的执行速度就变得很慢.因为当插入数值有序时,二叉树就是非平衡的了,排在一条线上,其实就变成了一个链表--它的快速查找.插入和删除指