红黑树的原理理解起来并不困难,无非是左右旋转,涂色。然而要编码出一个高效简洁的实现代码却挺复杂。近日学习Linux源码,对其红黑树实现作了注释,与大家分享一下。我贴的代码是我边理解边“抄写”出来的,和源始代码可能会有少许出入,但不影响理解。本文着重注释插入删除操作,其它部分不作重点。若要了解红黑树的基础知识或是Linux红黑树的使用,请另行参考其它资料。
先看一下节点定义:
-
typedef struct st_rb_node {
-
-
-
-
-
-
unsigned long parent_color;
-
#define RB_RED 0
-
#define RB_BLACK 1
-
struct st_rb_node *left, *right;
-
}__attribute__((aligned(sizeof(long)))) rb_node;
Linux的数据结构有个特点就是结构不包括数据,而是由数据来包括结构信息。由结构体获取数据信息是通过 CONTAINER_OF 这个宏来实现的,它利用了一些编译器的特性,有兴趣的可以参考Linux的链表源码。
头文件中其它主要内容如下(比较好理解,未作注释):
-
#define rb_parent(r) ((rb_node *)((r)->parent_color & ~3))
-
#define rb_color(r) ((r)->parent_color & 1)
-
#define rb_is_red(r) (!rb_color(r))
-
#define rb_is_black(r) rb_color(r)
-
#define rb_set_red(r) do { (r)->parent_color &= ~1; } while (0)
-
#define rb_set_black(r) do { (r)->parent_color |= 1; } while (0)
-
-
static inline void rb_set_parent(rb_node *node, rb_node *p) {
-
node->parent_color = (node->parent_color & 3) | (unsigned long) p;
-
}
-
-
static inline void rb_set_color(rb_node *node, int color) {
-
node->parent_color = (node->parent_color & ~1) | color;
-
}
-
-
#define RB_ROOT (rb_root) { NULL, }
-
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
-
-
#define RB_EMPTY_ROOT(root) ((root)->node == NULL)
-
#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
-
#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
-
-
void rb_insert_color(rb_node *node, rb_root *root);
-
void rb_erase(rb_node *node, rb_root *root);
-
-
rb_node * rb_next(const rb_node *node);
-
rb_node * rb_prev(const rb_node *node);
-
rb_node * rb_first(const rb_root *root);
-
rb_node * rb_last(const rb_root *root);
-
-
void rb_replace_node(rb_node *victim, rb_node *new, rb_root *root);
-
-
static inline void rb_link_node(rb_node *node, rb_node *p, rb_node **link) {
-
node->parent_color = (unsigned long) p;
-
node->left = node->right = NULL;
-
*link = node;
-
}
两个基本操作:左旋与右旋(未注释,仅为方便参考)
-
-
-
-
static void _rb_rotate_left(rb_node *node, rb_root *root) {
-
rb_node *right = node->right, *parent = rb_parent(node);
-
-
if ((node->right = right->left))
-
rb_set_parent(node->right, node);
-
-
right->left = node;
-
rb_set_parent(node, right);
-
-
if (parent) {
-
if (node == parent->left)
-
parent->left = right;
-
else
-
parent->right = right;
-
} else {
-
root->node = right;
-
}
-
rb_set_parent(right, parent);
-
}
-
-
-
-
-
static void _rb_rotate_right(rb_node *node, rb_root *root) {
-
rb_node *left = node->left, *parent = rb_parent(node);
-
-
if ((node->left = left->right))
-
rb_set_parent(node->left, node);
-
-
left->right = node;
-
rb_set_parent(node, left);
-
-
if (parent) {
-
if (node == parent->left)
-
parent->left = left;
-
else
-
parent->right = left;
-
} else {
-
root->node = left;
-
}
-
rb_set_parent(left, parent);
-
}
插入操作的实现(前提是节点已经插入在目标位置,下面的函数只负责修正树的性质):
-
-
-
-
-
void rb_insert_color(rb_node *node, rb_root *root) {
-
rb_node *parent, *gp;
-
-
-
-
-
while ((parent = rb_parent(node)) && rb_is_red(parent)) {
-
gp = rb_parent(parent);
-
-
if (parent == gp->left) {
-
-
-
-
-
register rb_node *uncle = gp->right;
-
if (uncle && rb_is_red(uncle)) {
-
-
-
-
rb_set_black(parent);
-
rb_set_black(uncle);
-
rb_set_red(gp);
-
-
-
-
-
node = gp;
-
continue;
-
}
-
-
-
-
-
if (node == parent->right) {
-
-
-
-
-
-
_rb_rotate_left(parent, root);
-
register rb_node *tmp = node;
-
node = parent;
-
parent = tmp;
-
}
-
-
-
-
-
-
rb_set_black(parent);
-
rb_set_red(gp);
-
_rb_rotate_right(gp, root);
-
return;
-
} else {
-
register rb_node *uncle = gp->left;
-
if (uncle && rb_is_red(uncle)) {
-
rb_set_black(parent);
-
rb_set_black(uncle);
-
rb_set_red(gp);
-
node = gp;
-
continue;
-
}
-
-
if (node == parent->left) {
-
_rb_rotate_right(parent, root);
-
register rb_node *tmp = node;
-
node = parent;
-
parent = tmp;
-
}
-
rb_set_black(parent);
-
rb_set_red(gp);
-
_rb_rotate_left(gp, root);
-
return;
-
}
-
}
-
-
-
-
-
-
rb_set_black(root->node);
-
}
最复杂的是删除操作,分为两部分。
删除第一步,移出节点:
第二步,简单移出如果破坏了树的性质,则需要修复:
-
-
-
-
-
-
-
-
-
static void _rb_erase_color(rb_node *node, rb_node *parent, rb_root *root) {
-
-
-
-
rb_node *other;
-
-
-
-
-
while ((!node || rb_is_black(node)) && node != root->node) {
-
-
-
-
-
-
-
-
-
-
-
-
if (parent->left == node) {
-
other = parent->right;
-
if (rb_is_red(other)) {
-
-
-
-
-
-
-
-
rb_set_black(other);
-
rb_set_red(parent);
-
_rb_rotate_left(parent, root);
-
-
-
-
other = parent->right;
-
}
-
-
-
-
-
if ((!other->left || rb_is_black(other->left)) &&
-
(!other->right || rb_is_black(other->right))) {
-
-
-
-
-
-
-
rb_set_red(other);
-
node = parent;
-
parent = rb_parent(node);
-
} else {
-
-
-
-
if (!other->right || rb_is_black(other->right)) {
-
-
-
-
-
-
-
rb_set_black(other->left);
-
rb_set_red(other);
-
_rb_rotate_right(other, root);
-
other = parent->right;
-
}
-
-
-
-
-
-
-
-
rb_set_color(other, rb_color(parent));
-
rb_set_black(parent);
-
rb_set_black(other->right);
-
_rb_rotate_left(parent, root);
-
-
-
-
-
node = root->node;
-
break;
-
}
-
} else {
-
other = parent->left;
-
if (rb_is_red(other)) {
-
rb_set_black(other);
-
rb_set_red(parent);
-
_rb_rotate_right(parent, root);
-
other = parent->left;
-
}
-
if ((!other->left || rb_is_black(other->left)) &&
-
(!other->right || rb_is_black(other->right))) {
-
rb_set_red(other);
-
node = parent;
-
parent = rb_parent(node);
-
} else {
-
if (!other->left || rb_is_black(other->left)) {
-
rb_set_black(other->right);
-
rb_set_red(other);
-
_rb_rotate_left(other, root);
-
other = parent->left;
-
}
-
rb_set_color(other, rb_color(parent));
-
rb_set_black(parent);
-
rb_set_black(other->left);
-
_rb_rotate_right(parent, root);
-
node = root->node;
-
break;
-
}
-
}
-
}
-
-
-
-
if (node)
-
rb_set_black(node);
-
}
参考地址:
阅读(3788) | 评论(0) | 转发(0) |