红联Linux门户
Linux帮助

Linux内核的红黑树RB_TREE和FreeBSD 8.0里面的AVL_TREE比较

发布时间:2014-12-15 21:44:17来源:linux网站作者:ztz0223

Linux内核的红黑树RB_TREE和FreeBSD 8.0里面的AVL_TREE比较之一 RB_TREE

这里不涉及到avl树和红黑树谁优谁劣,只是谈谈在两种实现的一些细节,以及最后给出一些性能比较。

这里先给出Linux下面的红黑树的实现,因为Linux下面的两个宏定义不好直接使用,原型如下:

#define rb_entry(ptr, type, member) container_of(ptr, type, member)  
 
#ifndef container_of  
/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:the pointer to the member.
 * @type:   the type of the container struct this is embedded in.
 * @member: the name of the member within the struct.
 *
 */ 
#define container_of(ptr, type, member) ({  \  
const typeof(((type *)0)->member) * __mptr = (ptr);  \ 
(type *)((char *)__mptr - offsetof(type, member)); }) 
#endif  
 
#ifndef offsetof  
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)  
#endif 

修改如下:

#ifndef offsetof  
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)  
#endif  
 
#ifndef container_of  
/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:the pointer to the member.
 * @type:   the type of the container struct this is embedded in.
 * @member: the name of the member within the struct.
 *
 * !!! modify the typeof marco, just use the rb_node
 */ 
#define container_of(ptr, type, member) \  
(((char *)ptr) - offsetof(type, member)) 
#endif  
 
#define rb_entry(ptr, type, member) container_of(ptr, type, member) 

语义可以认为不变的。

linux的RB_TREE源代码移植到vc上后,命名为:rb_tree.h, 如下:

/*
  Red Black Trees
  (C) 1999  Andrea Arcangeli <andrea@SUSE.de>
  
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
  linux/include/linux/rbtree.h
 
  To use rbtrees you'll have to implement your own insert and search cores.
  This will avoid us to use callbacks and to drop drammatically performances.
  I know it's not the cleaner way,  but in C (not in C++) to get
  performances and genericity...
 
  Some example of insert and search follows here. The search is a plain
  normal search over an ordered tree. The insert instead must be implemented
  in two steps: First, the code must insert the element in order as a red leaf
  in the tree, and then the support library function rb_insert_color() must
  be called. Such function will do the not trivial work to rebalance the
  rbtree, if necessary.
 
-----------------------------------------------------------------------
static inline struct page * rb_search_page_cache(struct inode * inode,
 unsigned long offset)
{
struct rb_node * n = inode->i_rb_page_cache.rb_node;
struct page * page;
 
while (n)
{
page = rb_entry(n, struct page, rb_page_cache);
 
if (offset < page->offset)
n = n->rb_left;
else if (offset > page->offset)
n = n->rb_right;
else
return page;
}
return NULL;
}
 
static inline struct page * __rb_insert_page_cache(struct inode * inode,
   unsigned long offset,
   struct rb_node * node)
{
struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
struct rb_node * parent = NULL;
struct page * page;
 
while (*p)
{
parent = *p;
page = rb_entry(parent, struct page, rb_page_cache);
 
if (offset < page->offset)
p = &(*p)->rb_left;
else if (offset > page->offset)
p = &(*p)->rb_right;
else
return page;
}
 
rb_link_node(node, parent, p);
 
return NULL;
}
 
static inline struct page * rb_insert_page_cache(struct inode * inode,
 unsigned long offset,
 struct rb_node * node)
{
struct page * ret;
if ((ret = __rb_insert_page_cache(inode, offset, node)))
goto out;
rb_insert_color(node, &inode->i_rb_page_cache);
 out:
return ret;
}
-----------------------------------------------------------------------
*/ 
 
#ifndef _LINUX_RBTREE_H  
#define _LINUX_RBTREE_H  
 
#define EXPORT_SYMBOL(i)  
 
#pragma pack (push)  
#pragma pack(4)  
struct rb_node 

unsigned long  rb_parent_color; 
#define RB_RED  0  
#define RB_BLACK1  
struct rb_node *rb_right; 
struct rb_node *rb_left; 
} ; 
 
#pragma pack (pop)  
/* The alignment might seem pointless, but allegedly CRIS needs it */ 
 
struct rb_root 

struct  rb_node *rb_node; 
int (*cmp)(void *src, void *dst); 
void(*insert)(struct rb_root *root, void *ins); 
void(*remove)(struct rb_root *root, void *del); 
}; 
 
 
#define rb_parent(r)   ((struct rb_node *)((r)->rb_parent_color & ~3))  
#define rb_color(r)   ((r)->rb_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)->rb_parent_color &= ~1; } while (0)  
#define rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)  
 
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) 

rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; 

static inline void rb_set_color(struct rb_node *rb, int color) 

rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; 

 
#ifndef offsetof  
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)  
#endif  
 
#ifndef container_of  
/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:the pointer to the member.
 * @type:   the type of the container struct this is embedded in.
 * @member: the name of the member within the struct.
 *
 * !!! modify the typeof marco, just use the rb_node
 */ 
#define container_of(ptr, type, member) \  
(((char *)ptr) - offsetof(type, member)) 
#endif  
 
#define RB_ROOT (struct rb_root) { NULL, }  
#define rb_entry(ptr, type, member) container_of(ptr, type, member)  
 
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)  
#define RB_EMPTY_NODE(node) (rb_parent(node) == node)  
#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))  
 
static inline void rb_init_node(struct rb_node *rb) 

rb->rb_parent_color = 0; 
rb->rb_right = NULL; 
rb->rb_left = NULL; 
RB_CLEAR_NODE(rb); 

 
extern void rb_insert_color(struct rb_node *, struct rb_root *); 
extern void rb_erase(struct rb_node *, struct rb_root *); 
 
typedef void (*rb_augment_f)(struct rb_node *node, void *data); 
 
extern void rb_augment_insert(struct rb_node *node, 
  rb_augment_f func, void *data); 
extern struct rb_node *rb_augment_erase_begin(struct rb_node *node); 
extern void rb_augment_erase_end(struct rb_node *node, 
 rb_augment_f func, void *data); 
 
/* Find logical next and previous nodes in a tree */ 
extern struct rb_node *rb_next(const struct rb_node *); 
extern struct rb_node *rb_prev(const struct rb_node *); 
extern struct rb_node *rb_first(const struct rb_root *); 
extern struct rb_node *rb_last(const struct rb_root *); 
 
/* Fast replacement of a single node without remove/rebalance/add/rebalance */ 
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new_node_node,  
struct rb_root *root); 
 
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, 
struct rb_node ** rb_link) 

node->rb_parent_color = (unsigned long )parent; 
node->rb_left = node->rb_right = NULL; 
 
*rb_link = node; 

 
#endif  /* _LINUX_RBTREE_H */

实现文件移植之后,命名为rb_tree.cpp, 如下:

/*
  Red Black Trees
  (C) 1999  Andrea Arcangeli <andrea@SUSE.de>
  (C) 2002  David Woodhouse <dwmw2@infradead.org>
  
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
  linux/lib/rbtree.c
*/ 
 
#include "rb_tree.h"  
 
 
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) 

struct rb_node *right = node->rb_right; 
struct rb_node *parent = rb_parent(node); 
 
if ((node->rb_right = right->rb_left)) 
rb_set_parent(right->rb_left, node); 
right->rb_left = node; 
 
rb_set_parent(right, parent); 
 
if (parent) 

if (node == parent->rb_left) 
parent->rb_left = right; 
else 
parent->rb_right = right; 

else 
root->rb_node = right; 
rb_set_parent(node, right); 

 
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) 

struct rb_node *left = node->rb_left; 
struct rb_node *parent = rb_parent(node); 
 
if ((node->rb_left = left->rb_right)) 
rb_set_parent(left->rb_right, node); 
left->rb_right = node; 
 
rb_set_parent(left, parent); 
 
if (parent) 

if (node == parent->rb_right) 
parent->rb_right = left; 
else 
parent->rb_left = left; 

else 
root->rb_node = left; 
rb_set_parent(node, left); 

 
void rb_insert_color(struct rb_node *node, struct rb_root *root) 

struct rb_node *parent, *gparent; 
 
while ((parent = rb_parent(node)) && rb_is_red(parent)) 

gparent = rb_parent(parent); 
 
if (parent == gparent->rb_left) 


register struct rb_node *uncle = gparent->rb_right; 
if (uncle && rb_is_red(uncle)) 

rb_set_black(uncle); 
rb_set_black(parent); 
rb_set_red(gparent); 
node = gparent; 
continue; 


 
if (parent->rb_right == node) 

register struct rb_node *tmp; 
__rb_rotate_left(parent, root); 
tmp = parent; 
parent = node; 
node = tmp; 

 
rb_set_black(parent); 
rb_set_red(gparent); 
__rb_rotate_right(gparent, root); 
} else { 

register struct rb_node *uncle = gparent->rb_left; 
if (uncle && rb_is_red(uncle)) 

rb_set_black(uncle); 
rb_set_black(parent); 
rb_set_red(gparent); 
node = gparent; 
continue; 


 
if (parent->rb_left == node) 

register struct rb_node *tmp; 
__rb_rotate_right(parent, root); 
tmp = parent; 
parent = node; 
node = tmp; 

 
rb_set_black(parent); 
rb_set_red(gparent); 
__rb_rotate_left(gparent, root); 


 
rb_set_black(root->rb_node); 

EXPORT_SYMBOL(rb_insert_color); 
 
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, 
 struct rb_root *root) 

struct rb_node *other; 
 
while ((!node || rb_is_black(node)) && node != root->rb_node) 

if (parent->rb_left == node) 

other = parent->rb_right; 
if (rb_is_red(other)) 

rb_set_black(other); 
rb_set_red(parent); 
__rb_rotate_left(parent, root); 
other = parent->rb_right; 

if ((!other->rb_left || rb_is_black(other->rb_left)) && 
(!other->rb_right || rb_is_black(other->rb_right))) 

rb_set_red(other); 
node = parent; 
parent = rb_parent(node); 

else 

if (!other->rb_right || rb_is_black(other->rb_right)) 

rb_set_black(other->rb_left); 
rb_set_red(other); 
__rb_rotate_right(other, root); 
other = parent->rb_right; 

rb_set_color(other, rb_color(parent)); 
rb_set_black(parent); 
rb_set_black(other->rb_right); 
__rb_rotate_left(parent, root); 
node = root->rb_node; 
break; 


else 

other = parent->rb_left; 
if (rb_is_red(other)) 

rb_set_black(other); 
rb_set_red(parent); 
__rb_rotate_right(parent, root); 
other = parent->rb_left; 

if ((!other->rb_left || rb_is_black(other->rb_left)) && 
(!other->rb_right || rb_is_black(other->rb_right))) 

rb_set_red(other); 
node = parent; 
parent = rb_parent(node); 

else 

if (!other->rb_left || rb_is_black(other->rb_left)) 

rb_set_black(other->rb_right); 
rb_set_red(other); 
__rb_rotate_left(other, root); 
other = parent->rb_left; 

rb_set_color(other, rb_color(parent)); 
rb_set_black(parent); 
rb_set_black(other->rb_left); 
__rb_rotate_right(parent, root); 
node = root->rb_node; 
break; 



if (node) 
rb_set_black(node); 

 
void rb_erase(struct rb_node *node, struct rb_root *root) 

struct rb_node *child, *parent; 
int color; 
 
if (!node->rb_left) 
child = node->rb_right; 
else if (!node->rb_right) 
child = node->rb_left; 
else 

struct rb_node *old = node, *left; 
 
node = node->rb_right; 
while ((left = node->rb_left) != NULL) 
node = left; 
 
if (rb_parent(old)) { 
if (rb_parent(old)->rb_left == old) 
rb_parent(old)->rb_left = node; 
else 
rb_parent(old)->rb_right = node; 
} else 
root->rb_node = node; 
 
child = node->rb_right; 
parent = rb_parent(node); 
color = rb_color(node); 
 
if (parent == old) { 
parent = node; 
} else { 
if (child) 
rb_set_parent(child, parent); 
parent->rb_left = child; 
 
node->rb_right = old->rb_right; 
rb_set_parent(old->rb_right, node); 

 
node->rb_parent_color = old->rb_parent_color; 
node->rb_left = old->rb_left; 
rb_set_parent(old->rb_left, node); 
 
goto color; 

 
parent = rb_parent(node); 
color = rb_color(node); 
 
if (child) 
rb_set_parent(child, parent); 
if (parent) 

if (parent->rb_left == node) 
parent->rb_left = child; 
else 
parent->rb_right = child; 

else 
root->rb_node = child; 
 
 color: 
if (color == RB_BLACK) 
__rb_erase_color(child, parent, root); 

EXPORT_SYMBOL(rb_erase); 
 
static void rb_augment_path(struct rb_node *node, rb_augment_f func, void *data) 

struct rb_node *parent; 
 
up: 
func(node, data); 
parent = rb_parent(node); 
if (!parent) 
return; 
 
if (node == parent->rb_left && parent->rb_right) 
func(parent->rb_right, data); 
else if (parent->rb_left) 
func(parent->rb_left, data); 
 
node = parent; 
goto up; 

 
/*
 * after inserting @node into the tree, update the tree to account for
 * both the new_node entry and any damage done by rebalance
 */ 
void rb_augment_insert(struct rb_node *node, rb_augment_f func, void *data) 

if (node->rb_left) 
node = node->rb_left; 
else if (node->rb_right) 
node = node->rb_right; 
 
rb_augment_path(node, func, data); 

EXPORT_SYMBOL(rb_augment_insert); 
 
/*
 * before removing the node, find the deepest node on the rebalance path
 * that will still be there after @node gets removed
 */ 
struct rb_node *rb_augment_erase_begin(struct rb_node *node) 

struct rb_node *deepest; 
 
if (!node->rb_right && !node->rb_left) 
deepest = rb_parent(node); 
else if (!node->rb_right) 
deepest = node->rb_left; 
else if (!node->rb_left) 
deepest = node->rb_right; 
else { 
deepest = rb_next(node); 
if (deepest->rb_right) 
deepest = deepest->rb_right; 
else if (rb_parent(deepest) != node) 
deepest = rb_parent(deepest); 

 
return deepest; 

EXPORT_SYMBOL(rb_augment_erase_begin); 
 
/*
 * after removal, update the tree to account for the removed entry
 * and any rebalance damage.
 */ 
void rb_augment_erase_end(struct rb_node *node, rb_augment_f func, void *data) 

if (node) 
rb_augment_path(node, func, data); 

EXPORT_SYMBOL(rb_augment_erase_end); 
 
/*
 * This function returns the first node (in sort order) of the tree.
 */ 
struct rb_node *rb_first(const struct rb_root *root) 

struct rb_node  *n; 
 
n = root->rb_node; 
if (!n) 
return NULL; 
while (n->rb_left) 
n = n->rb_left; 
return n; 

EXPORT_SYMBOL(rb_first); 
 
struct rb_node *rb_last(const struct rb_root *root) 

struct rb_node  *n; 
 
n = root->rb_node; 
if (!n) 
return NULL; 
while (n->rb_right) 
n = n->rb_right; 
return n; 

EXPORT_SYMBOL(rb_last); 
 
struct rb_node *rb_next(const struct rb_node *node) 

struct rb_node *parent; 
 
if (rb_parent(node) == node) 
return NULL; 
 
/* If we have a right-hand child, go down and then left as far
   as we can. */ 
if (node->rb_right) { 
node = node->rb_right;  
while (node->rb_left) 
node=node->rb_left; 
return (struct rb_node *)node; 

 
/* No right-hand children.  Everything down and left is
   smaller than us, so any 'next' node must be in the general
   direction of our parent. Go up the tree; any time the
   ancestor is a right-hand child of its parent, keep going
   up. First time it's a left-hand child of its parent, said
   parent is our 'next' node. */ 
while ((parent = rb_parent(node)) && node == parent->rb_right) 
node = parent; 
 
return parent; 

EXPORT_SYMBOL(rb_next); 
 
struct rb_node *rb_prev(const struct rb_node *node) 

struct rb_node *parent; 
 
if (rb_parent(node) == node) 
return NULL; 
 
/* If we have a left-hand child, go down and then right as far
   as we can. */ 
if (node->rb_left) { 
node = node->rb_left;  
while (node->rb_right) 
node=node->rb_right; 
return (struct rb_node *)node; 

 
/* No left-hand children. Go up till we find an ancestor which
   is a right-hand child of its parent */ 
while ((parent = rb_parent(node)) && node == parent->rb_left) 
node = parent; 
 
return parent; 

EXPORT_SYMBOL(rb_prev); 
 
void rb_replace_node(struct rb_node *victim, struct rb_node *new_node, 
 struct rb_root *root) 

struct rb_node *parent = rb_parent(victim); 
 
/* Set the surrounding nodes to point to the replacement */ 
if (parent) { 
if (victim == parent->rb_left) 
parent->rb_left = new_node; 
else 
parent->rb_right = new_node; 
} else { 
root->rb_node = new_node; 

if (victim->rb_left) 
rb_set_parent(victim->rb_left, new_node); 
if (victim->rb_right) 
rb_set_parent(victim->rb_right, new_node); 
 
/* Copy the pointers/colour from the victim to the replacement */ 
*new_node = *victim; 

EXPORT_SYMBOL(rb_replace_node); 

其实,可以看出,linux内核里面并没有提供直接可以用的insert delete 以及walk遍历的函数接口,linux提供的是最基本一个插入节点后的re-fixup,删除后的re-fixup,以及walk需要的get-firt, get-next等等。

这里是需要自己提供插入,删除,以及walk函数的,相比freebsd的avl树,完全就是一步到位了,而且好用很多,这里不谈谁好用,然后举例简单说说怎么使用linux的基本的这些函数,晚点会比较二者在插入删除以及walk方面的优劣。

自己提供相应的一些接口了,时间有限随便写写:

应用头文件,rb_tree_main.h:

#ifndef RB_TREE_MAIN_H  
#define RB_TREE_MAIN_H  
 
#include "rb_tree.h"  
 
voidmy_insert(struct rb_root *root, void *ins); 
int my_cmp(void *src, void *dest); 
voidmy_rb_walk(const struct rb_root *root); 
voidmy_remove(struct rb_root *g_my_root, void *del); 
 
#endif 

man文件:rb_tree_main.cpp

// rb_tree_main.cpp : Defines the entry point for the console application.  
//  
#include <string.h>  
#include <stdlib.h>  
#include "rb_tree.h"  
#include "rb_tree_main.h"  
 
typedef struct my_rb 

int rand_val; 
struct rb_node my_rb_node; 
}my_rb; 
 
struct rb_root g_my_root = {NULL, my_cmp, my_insert, my_remove}; 
 
void my_insert(struct rb_root *root, void *ins) 

struct my_rb *iter; 
struct my_rb *src = (struct my_rb *)ins; 
struct rb_node **p = &root->rb_node; 
struct rb_node *parent = NULL; 
 
if(!ins) 

return; 

 
while (*p != NULL) { 
parent = *p; 
iter = (struct my_rb *)rb_entry(parent, struct my_rb, my_rb_node); 
 
if (root->cmp(src, iter) < 0) 
p = &(*p)->rb_left; 
else 
p = &(*p)->rb_right; 

 
rb_link_node(&src->my_rb_node, parent, p); 
rb_insert_color(&src->my_rb_node, root); 

 
int my_cmp(void *src, void *dest) 

struct my_rb *my_src = (struct my_rb *)src; 
struct my_rb *my_dest = (struct my_rb *)dest; 
 
if(!my_src || !my_dest) 

return 0; 

 
if(my_src->rand_val < my_dest->rand_val) 

return -1; 

else if(my_src->rand_val > my_dest->rand_val) 

return 1; 

else 

return 0; 


 
void my_remove(struct rb_root *g_my_root, void *del) 

struct my_rb*entry  = NULL; 
struct my_rb*del_node   = (struct my_rb *)del; 
struct rb_node  *n  = NULL;  
 
if(!g_my_root || !del) 

return; 

 
n = g_my_root->rb_node; 
 
while (n) 

entry = (struct my_rb *)rb_entry(n, struct my_rb, my_rb_node); 
 
if (g_my_root->cmp(entry, del_node) > 0) 

n = n->rb_left; 

else if (g_my_root->cmp(entry, del_node) < 0) 

n = n->rb_right; 

else 

rb_erase(n, g_my_root); 
free(entry); 
entry = NULL; 
return ; 


 
return ; 

 
 
void my_rb_walk(const struct rb_root *root) 

struct rb_node *temp = rb_first(root); 
struct my_rb *my_entry = NULL; 
 
while(temp) 

my_entry = (struct my_rb *)rb_entry(temp, my_rb, my_rb_node); 
printf("node with rand_val %d .\n", my_entry->rand_val); 
 
temp = rb_next(temp); 


 
int main(int argc, char* argv[]) 

struct my_rb *my_rb_node = NULL; 
 
struct my_rb del_node = {4, {0}}; 
 
for (int i = 0; i < 5; i++) 

my_rb_node = (struct my_rb *)malloc(sizeof *my_rb_node); 
memset(my_rb_node, 0, sizeof *my_rb_node); 
my_rb_node->rand_val = i; 
g_my_root.insert(&g_my_root, my_rb_node); 

 
my_rb_walk(&g_my_root); 
 
g_my_root.remove(&g_my_root, &del_node); 
 
my_rb_walk(&g_my_root); 
 
return 0; 

注意四点:

1、insert里面的双重指针,直接找到要插入的位置的父节点,省去了一堆赋值比如parent->left or right = p, p->parent 啥啥啥的,直接在父节点(叶子节点)的左或者右节点NULL的取一次地址,然后,地址上面写值,不细说了;

2、插入的节点应该动态分配,或者是已经静态分配好的多个节点

3、删除操作,内核提供的只是re-fixup,不会帮你释放内存的,我们要做的是找到这个节点,然后调用内核提供的rb_erase,把节点从rb树上移去,如果是动态分配,再释放之。

4、内核的红黑树是带有parent属性的,只是么有用指针,而是把parent和left和right子标记用了一个字段而已:

unsigned long  rb_parent_color; 

最低的一位用作了left和right的flag,最高的31位,用作存储parent指针的地址,这种rb树就要求插入的节点地址必须是偶数的,一般的cpu架构使得分配出来的内存都是偶数地址对齐的了,但是有些也会以奇数开始,比如ppc,就可能动态分配出一个节点就是从奇数地址开始的。只要是偶数地址开始那么地址的最低位一定是0了。

 其实在3.0.1的内核里面是这种rb设计,在早期的内核里面rb_node就是另外一种设计了,是引入了parent指针的,比如2.6.11的内核的结构体设计如下:

struct rb_node 

struct rb_node *rb_parent; 
int rb_color; 
#define RB_RED  0  
#define RB_BLACK1  
struct rb_node *rb_right; 
struct rb_node *rb_left; 
}; 

其实在freebsd 8.0的avl树64位设计就是这种,32二位的设计类似于早些时候的内核的rb树的节点设计:

#ifndef _LP64  
 
struct avl_node { 
struct avl_node *avl_child[2];  /* left/right children */ 
struct avl_node *avl_parent;/* this node's parent */ 
unsigned short avl_child_index; /* my index in parent's avl_child[] */ 
short avl_balance;  /* balance value: -1, 0, +1 */ 
}; 
 
#else /* _LP64 */  
 
/*
 * for 64 bit machines, avl_pcb contains parent pointer, balance and child_index
 * values packed in the following manner:
 *
 * |63  3|2|1  0 |
 * |-------------------------------------|-----------------|-------------|
 * |  avl_parent hi order bits   | avl_child_index | avl_balance |
 * | | | + 1 |
 * |-------------------------------------|-----------------|-------------|
 *
 */ 
struct avl_node { 
struct avl_node *avl_child[2];  /* left/right children nodes */ 
uintptr_t avl_pcb;  /* parent, child_index, balance */ 
}; 

#endif  

说这么多,以后再说freebsd的avl树咋用的吧。