您的位置:首页 > 运维架构 > Linux

红黑树(三)之 Linux内核中红黑树的经典实现

2014-04-02 20:22 2216 查看

概要

前面分别介绍了红黑树的理论知识 以及 通过C语言实现了红黑树。本章继续会红黑树进行介绍,下面将Linux 内核中的红黑树单独移植出来进行测试验证。若读者对红黑树的理论知识不熟悉,建立先学习红黑树的理论知识,再来学习本章。

转载请注明出处:https://www.geek-share.com/detail/2607441322.html

更多内容:数据结构与算法系列 目录

(01) 红黑树(一)之 原理和算法详细介绍
(02) 红黑树(二)之 C语言的实现
(03) 红黑树(三)之 Linux内核中红黑树的经典实现
(04) 红黑树(四)之 C++的实现
(05) 红黑树(五)之 Java的实现
(06) 红黑树(六)之 参考资料

Linux内核中红黑树(完整源码)

红黑树的实现文件(rbtree.h)

/**
* 根据Linux Kernel定义的红黑树(Red Black Tree)
*
* @author skywang
* @date 2013/11/18
*/

#include <stdio.h>
#include <stdlib.h>
#include "rbtree.h"

#define CHECK_INSERT 0    // "插入"动作的检测开关(0,关闭;1,打开)
#define CHECK_DELETE 0    // "删除"动作的检测开关(0,关闭;1,打开)
#define LENGTH(a) ( (sizeof(a)) / (sizeof(a[0])) )

typedef int Type;

struct my_node {
struct rb_node rb_node;    // 红黑树节点
Type key;                // 键值
// ... 用户自定义的数据
};

/*
* 查找"红黑树"中键值为key的节点。没找到的话,返回NULL。
*/
struct my_node *my_search(struct rb_root *root, Type key)
{
struct rb_node *rbnode = root->rb_node;

while (rbnode!=NULL)
{
struct my_node *mynode = container_of(rbnode, struct my_node, rb_node);

if (key < mynode->key)
rbnode = rbnode->rb_left;
else if (key > mynode->key)
rbnode = rbnode->rb_right;
else
return mynode;
}

return NULL;
}

/*
* 将key插入到红黑树中。插入成功,返回0;失败返回-1。
*/
int my_insert(struct rb_root *root, Type key)
{
struct my_node *mynode; // 新建结点
struct rb_node **tmp = &(root->rb_node), *parent = NULL;

/* Figure out where to put new node */
while (*tmp)
{
struct my_node *my = container_of(*tmp, struct my_node, rb_node);

parent = *tmp;
if (key < my->key)
tmp = &((*tmp)->rb_left);
else if (key > my->key)
tmp = &((*tmp)->rb_right);
else
return -1;
}

// 如果新建结点失败,则返回。
if ((mynode=malloc(sizeof(struct my_node))) == NULL)
return -1;
mynode->key = key;

/* Add new node and rebalance tree. */
rb_link_node(&mynode->rb_node, parent, tmp);
rb_insert_color(&mynode->rb_node, root);

return 0;
}

/*
* 删除键值为key的结点
*/
void my_delete(struct rb_root *root, Type key)
{
struct my_node *mynode;

// 在红黑树中查找key对应的节点mynode
if ((mynode = my_search(root, key)) == NULL)
return ;

// 从红黑树中删除节点mynode
rb_erase(&mynode->rb_node, root);
free(mynode);
}

/*
* 打印"红黑树"
*/
static void print_rbtree(struct rb_node *tree, Type key, int direction)
{
if(tree != NULL)
{
if(direction==0)    // tree是根节点
printf("%2d(B) is root\n", key);
else                // tree是分支节点
printf("%2d(%s) is %2d's %6s child\n", key, rb_is_black(tree)?"B":"R", key, direction==1?"right" : "left");

if (tree->rb_left)
print_rbtree(tree->rb_left, rb_entry(tree->rb_left, struct my_node, rb_node)->key, -1);
if (tree->rb_right)
print_rbtree(tree->rb_right,rb_entry(tree->rb_right, struct my_node, rb_node)->key,  1);
}
}

void my_print(struct rb_root *root)
{
if (root!=NULL && root->rb_node!=NULL)
print_rbtree(root->rb_node, rb_entry(root->rb_node, struct my_node, rb_node)->key,  0);
}

void main()
{
int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80};
int i, ilen=LENGTH(a);
struct rb_root mytree = RB_ROOT;

printf("== 原始数据: ");
for(i=0; i<ilen; i++)
printf("%d ", a[i]);
printf("\n");

for (i=0; i < ilen; i++)
{
my_insert(&mytree, a[i]);
#if CHECK_INSERT
printf("== 添加节点: %d\n", a[i]);
printf("== 树的详细信息: \n");
my_print(&mytree);
printf("\n");
#endif

}

#if CHECK_DELETE
for (i=0; i<ilen; i++) {
my_delete(&mytree, a[i]);

printf("== 删除节点: %d\n", a[i]);
printf("== 树的详细信息: \n");
my_print(&mytree);
printf("\n");
}
#endif
}


View Code
rbtree.h和rbtree.c基本上是从Linux 3.0的Kernel中移植出来的。仅仅只添加了offestof和container_of两个宏,这两个宏在文章"Linux内核中双向链表的经典实现"中已经介绍过了,这里就不再重复说明了。
test.c中包含了两部分内容:一是,基于内核红黑树接口,自定义的一个结构体,并提供了相应的接口(添加、删除、搜索、打印)。二是,包含了相应的测试程序。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: