感谢支持
我们一直在努力

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

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


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


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



  1. #define rb_entry(ptr, type, member) container_of(ptr, type, member)   

  2.   

  3. #ifndef container_of   

  4. /** 

  5.  * container_of – cast a member of a structure out to the containing structure 

  6.  * @ptr:    the pointer to the member. 

  7.  * @type:   the type of the container struct this is embedded in. 

  8.  * @member: the name of the member within the struct. 

  9.  * 

  10.  */  

  11. #define container_of(ptr, type, member) ({          \   

  12.     const typeof(((type *)0)->member) * __mptr = (ptr);  \  

  13.     (type *)((char *)__mptr – offsetof(type, member)); })  

  14. #endif   

  15.   

  16. #ifndef offsetof   

  17. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)   

  18. #endif  

修改如下:


  1. #ifndef offsetof   

  2. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)   

  3. #endif   

  4.   

  5. #ifndef container_of   

  6. /** 

  7.  * container_of – cast a member of a structure out to the containing structure 

  8.  * @ptr:    the pointer to the member. 

  9.  * @type:   the type of the container struct this is embedded in. 

  10.  * @member: the name of the member within the struct. 

  11.  * 

  12.  * !!! modify the typeof marco, just use the rb_node 

  13.  */  

  14. #define container_of(ptr, type, member)         \   

  15.     (((char *)ptr) – offsetof(type, member))  

  16. #endif   

  17.   

  18. #define rb_entry(ptr, type, member) container_of(ptr, type, member)  

语义可以认为不变的。


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


  1. /* 

  2.   Red Black Trees 

  3.   (C) 1999  Andrea Arcangeli <andrea@SUSE.de> 

  4.    

  5.   This program is free software; you can Redistribute it and/or modify 

  6.   it under the terms of the GNU General Public License as published by 

  7.   the Free Software Foundation; either version 2 of the License, or 

  8.   (at your option) any later version. 

  9.  

  10.   This program is distributed in the hope that it will be useful, 

  11.   but WITHOUT ANY WARRANTY; without even the implied warranty of 

  12.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 

  13.   GNU General Public License for more details. 

  14.  

  15.   You should have received a copy of the GNU General Public License 

  16.   along with this program; if not, write to the Free Software 

  17.   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

  18.  

  19.   linux/include/linux/rbtree.h 

  20.  

  21.   To use rbtrees you’ll have to implement your own insert and search cores. 

  22.   This will avoid us to use callbacks and to drop drammatically performances. 

  23.   I know it’s not the cleaner way,  but in C (not in C++) to get 

  24.   performances and genericity… 

  25.  

  26.   Some example of insert and search follows here. The search is a plain 

  27.   normal search over an ordered tree. The insert instead must be implemented 

  28.   in two steps: First, the code must insert the element in order as a red leaf 

  29.   in the tree, and then the support library function rb_insert_color() must 

  30.   be called. Such function will do the not trivial work to rebalance the 

  31.   rbtree, if necessary. 

  32.  

  33. ———————————————————————– 

  34. static inline struct page * rb_search_page_cache(struct inode * inode, 

  35.                          unsigned long offset) 

  36. { 

  37.     struct rb_node * n = inode->i_rb_page_cache.rb_node; 

  38.     struct page * page; 

  39.  

  40.     while (n) 

  41.     { 

  42.         page = rb_entry(n, struct page, rb_page_cache); 

  43.  

  44.         if (offset < page->offset) 

  45.             n = n->rb_left; 

  46.         else if (offset > page->offset) 

  47.             n = n->rb_right; 

  48.         else 

  49.             return page; 

  50.     } 

  51.     return NULL; 

  52. } 

  53.  

  54. static inline struct page * __rb_insert_page_cache(struct inode * inode, 

  55.                            unsigned long offset, 

  56.                            struct rb_node * node) 

  57. { 

  58.     struct rb_node ** p = &inode->i_rb_page_cache.rb_node; 

  59.     struct rb_node * parent = NULL; 

  60.     struct page * page; 

  61.  

  62.     while (*p) 

  63.     { 

  64.         parent = *p; 

  65.         page = rb_entry(parent, struct page, rb_page_cache); 

  66.  

  67.         if (offset < page->offset) 

  68.             p = &(*p)->rb_left; 

  69.         else if (offset > page->offset) 

  70.             p = &(*p)->rb_right; 

  71.         else 

  72.             return page; 

  73.     } 

  74.  

  75.     rb_link_node(node, parent, p); 

  76.  

  77.     return NULL; 

  78. } 

  79.  

  80. static inline struct page * rb_insert_page_cache(struct inode * inode, 

  81.                          unsigned long offset, 

  82.                          struct rb_node * node) 

  83. { 

  84.     struct page * ret; 

  85.     if ((ret = __rb_insert_page_cache(inode, offset, node))) 

  86.         goto out; 

  87.     rb_insert_color(node, &inode->i_rb_page_cache); 

  88.  out: 

  89.     return ret; 

  90. } 

  91. ———————————————————————– 

  92. */  

  93.   

  94. #ifndef _LINUX_RBTREE_H   

  95. #define _LINUX_RBTREE_H   

  96.   

  97. #define EXPORT_SYMBOL(i)   

  98.   

  99. #pragma pack (push)   

  100. #pragma pack(4)   

  101. struct rb_node  

  102. {  

  103.     unsigned long  rb_parent_color;  

  104. #define RB_RED      0   

  105. #define RB_BLACK    1   

  106.     struct rb_node *rb_right;  

  107.     struct rb_node *rb_left;  

  108. } ;  

  109.   

  110. #pragma pack (pop)   

  111.     /* The alignment might seem pointless, but allegedly CRIS needs it */  

  112.   

  113. struct rb_root  

  114. {  

  115.     struct  rb_node *rb_node;  

  116.     int     (*cmp)(void *src, void *dst);  

  117.     void    (*insert)(struct rb_root *root, void *ins);  

  118.     void    (*remove)(struct rb_root *root, void *del);  

  119. };  

  120.   

  121.   

  122. #define rb_parent(r)   ((struct rb_node *)((r)->rb_parent_color & ~3))   

  123. #define rb_color(r)   ((r)->rb_parent_color & 1)   

  124. #define rb_is_red(r)   (!rb_color(r))   

  125. #define rb_is_black(r) rb_color(r)   

  126. #define rb_set_red(r)  do { (r)->rb_parent_color &= ~1; } while (0)   

  127. #define rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)   

  128.   

  129. static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)  

  130. {  

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

  132. }  

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

  134. {  

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

  136. }  

  137.   

  138. #ifndef offsetof   

  139. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)   

  140. #endif   

  141.   

  142. #ifndef container_of   

  143. /** 

  144.  * container_of – cast a member of a structure out to the containing structure 

  145.  * @ptr:    the pointer to the member. 

  146.  * @type:   the type of the container struct this is embedded in. 

  147.  * @member: the name of the member within the struct. 

  148.  * 

  149.  * !!! modify the typeof marco, just use the rb_node 

  150.  */  

  151. #define container_of(ptr, type, member)         \   

  152.     (((char *)ptr) – offsetof(type, member))  

  153. #endif   

  154.   

  155. #define RB_ROOT (struct rb_root) { NULL, }   

  156. #define rb_entry(ptr, type, member) container_of(ptr, type, member)   

  157.   

  158. #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)   

  159. #define RB_EMPTY_NODE(node) (rb_parent(node) == node)   

  160. #define RB_CLEAR_NODE(node) (rb_set_parent(node, node))   

  161.   

  162. static inline void rb_init_node(struct rb_node *rb)  

  163. {  

  164.     rb->rb_parent_color = 0;  

  165.     rb->rb_right = NULL;  

  166.     rb->rb_left = NULL;  

  167.     RB_CLEAR_NODE(rb);  

  168. }  

  169.   

  170. extern void rb_insert_color(struct rb_node *, struct rb_root *);  

  171. extern void rb_erase(struct rb_node *, struct rb_root *);  

  172.   

  173. typedef void (*rb_augment_f)(struct rb_node *node, void *data);  

  174.   

  175. extern void rb_augment_insert(struct rb_node *node,  

  176.                   rb_augment_f func, void *data);  

  177. extern struct rb_node *rb_augment_erase_begin(struct rb_node *node);  

  178. extern void rb_augment_erase_end(struct rb_node *node,  

  179.                  rb_augment_f func, void *data);  

  180.   

  181. /* Find logical next and previous nodes in a tree */  

  182. extern struct rb_node *rb_next(const struct rb_node *);  

  183. extern struct rb_node *rb_prev(const struct rb_node *);  

  184. extern struct rb_node *rb_first(const struct rb_root *);  

  185. extern struct rb_node *rb_last(const struct rb_root *);  

  186.   

  187. /* Fast replacement of a single node without remove/rebalance/add/rebalance */  

  188. extern void rb_replace_node(struct rb_node *victim, struct rb_node *new_node_node,   

  189.                 struct rb_root *root);  

  190.   

  191. static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,  

  192.                 struct rb_node ** rb_link)  

  193. {  

  194.     node->rb_parent_color = (unsigned long )parent;  

  195.     node->rb_left = node->rb_right = NULL;  

  196.   

  197.     *rb_link = node;  

  198. }  

  199.   

  200. #endif  /* _LINUX_RBTREE_H */  

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


  1. /* 

  2.   Red Black Trees 

  3.   (C) 1999  Andrea Arcangeli <andrea@SUSE.de> 

  4.   (C) 2002  David Woodhouse <dwmw2@infradead.org> 

  5.    

  6.   This program is free software; you can Redistribute it and/or modify 

  7.   it under the terms of the GNU General Public License as published by 

  8.   the Free Software Foundation; either version 2 of the License, or 

  9.   (at your option) any later version. 

  10.  

  11.   This program is distributed in the hope that it will be useful, 

  12.   but WITHOUT ANY WARRANTY; without even the implied warranty of 

  13.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 

  14.   GNU General Public License for more details. 

  15.  

  16.   You should have received a copy of the GNU General Public License 

  17.   along with this program; if not, write to the Free Software 

  18.   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

  19.  

  20.   linux/lib/rbtree.c 

  21. */  

  22.   

  23. #include “rb_tree.h”   

  24.   

  25.   

  26. static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)  

  27. {  

  28.     struct rb_node *right = node->rb_right;  

  29.     struct rb_node *parent = rb_parent(node);  

  30.   

  31.     if ((node->rb_right = right->rb_left))  

  32.         rb_set_parent(right->rb_left, node);  

  33.     right->rb_left = node;  

  34.   

  35.     rb_set_parent(right, parent);  

  36.   

  37.     if (parent)  

  38.     {  

  39.         if (node == parent->rb_left)  

  40.             parent->rb_left = right;  

  41.         else  

  42.             parent->rb_right = right;  

  43.     }  

  44.     else  

  45.         root->rb_node = right;  

  46.     rb_set_parent(node, right);  

  47. }  

  48.   

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

  50. {  

  51.     struct rb_node *left = node->rb_left;  

  52.     struct rb_node *parent = rb_parent(node);  

  53.   

  54.     if ((node->rb_left = left->rb_right))  

  55.         rb_set_parent(left->rb_right, node);  

  56.     left->rb_right = node;  

  57.   

  58.     rb_set_parent(left, parent);  

  59.   

  60.     if (parent)  

  61.     {  

  62.         if (node == parent->rb_right)  

  63.             parent->rb_right = left;  

  64.         else  

  65.             parent->rb_left = left;  

  66.     }  

  67.     else  

  68.         root->rb_node = left;  

  69.     rb_set_parent(node, left);  

  70. }  

  71.   

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

  73. {  

  74.     struct rb_node *parent, *gparent;  

  75.   

  76.     while ((parent = rb_parent(node)) && rb_is_red(parent))  

  77.     {  

  78.         gparent = rb_parent(parent);  

  79.   

  80.         if (parent == gparent->rb_left)  

  81.         {  

  82.             {  

  83.                 register struct rb_node *uncle = gparent->rb_right;  

  84.                 if (uncle && rb_is_red(uncle))  

  85.                 {  

  86.                     rb_set_black(uncle);  

  87.                     rb_set_black(parent);  

  88.                     rb_set_red(gparent);  

  89.                     node = gparent;  

  90.                     continue;  

  91.                 }  

  92.             }  

  93.   

  94.             if (parent->rb_right == node)  

  95.             {  

  96.                 register struct rb_node *tmp;  

  97.                 __rb_rotate_left(parent, root);  

  98.                 tmp = parent;  

  99.                 parent = node;  

  100.                 node = tmp;  

  101.             }  

  102.   

  103.             rb_set_black(parent);  

  104.             rb_set_red(gparent);  

  105.             __rb_rotate_right(gparent, root);  

  106.         } else {  

  107.             {  

  108.                 register struct rb_node *uncle = gparent->rb_left;  

  109.                 if (uncle && rb_is_red(uncle))  

  110.                 {  

  111.                     rb_set_black(uncle);  

  112.                     rb_set_black(parent);  

  113.                     rb_set_red(gparent);  

  114.                     node = gparent;  

  115.                     continue;  

  116.                 }  

  117.             }  

  118.   

  119.             if (parent->rb_left == node)  

  120.             {  

  121.                 register struct rb_node *tmp;  

  122.                 __rb_rotate_right(parent, root);  

  123.                 tmp = parent;  

  124.                 parent = node;  

  125.                 node = tmp;  

  126.             }  

  127.   

  128.             rb_set_black(parent);  

  129.             rb_set_red(gparent);  

  130.             __rb_rotate_left(gparent, root);  

  131.         }  

  132.     }  

  133.   

  134.     rb_set_black(root->rb_node);  

  135. }  

  136. EXPORT_SYMBOL(rb_insert_color);  

  137.   

  138. static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,  

  139.                  struct rb_root *root)  

  140. {  

  141.     struct rb_node *other;  

  142.   

  143.     while ((!node || rb_is_black(node)) && node != root->rb_node)  

  144.     {  

  145.         if (parent->rb_left == node)  

  146.         {  

  147.             other = parent->rb_right;  

  148.             if (rb_is_red(other))  

  149.             {  

  150.                 rb_set_black(other);  

  151.                 rb_set_red(parent);  

  152.                 __rb_rotate_left(parent, root);  

  153.                 other = parent->rb_right;  

  154.             }  

  155.             if ((!other->rb_left || rb_is_black(other->rb_left)) &&  

  156.                 (!other->rb_right || rb_is_black(other->rb_right)))  

  157.             {  

  158.                 rb_set_red(other);  

  159.                 node = parent;  

  160.                 parent = rb_parent(node);  

  161.             }  

  162.             else  

  163.             {  

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

  165.                 {  

  166.                     rb_set_black(other->rb_left);  

  167.                     rb_set_red(other);  

  168.                     __rb_rotate_right(other, root);  

  169.                     other = parent->rb_right;  

  170.                 }  

  171.                 rb_set_color(other, rb_color(parent));  

  172.                 rb_set_black(parent);  

  173.                 rb_set_black(other->rb_right);  

  174.                 __rb_rotate_left(parent, root);  

  175.                 node = root->rb_node;  

  176.                 break;  

  177.             }  

  178.         }  

  179.         else  

  180.         {  

  181.             other = parent->rb_left;  

  182.             if (rb_is_red(other))  

  183.             {  

  184.                 rb_set_black(other);  

  185.                 rb_set_red(parent);  

  186.                 __rb_rotate_right(parent, root);  

  187.                 other = parent->rb_left;  

  188.             }  

  189.             if ((!other->rb_left || rb_is_black(other->rb_left)) &&  

  190.                 (!other->rb_right || rb_is_black(other->rb_right)))  

  191.             {  

  192.                 rb_set_red(other);  

  193.                 node = parent;  

  194.                 parent = rb_parent(node);  

  195.             }  

  196.             else  

  197.             {  

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

  199.                 {  

  200.                     rb_set_black(other->rb_right);  

  201.                     rb_set_red(other);  

  202.                     __rb_rotate_left(other, root);  

  203.                     other = parent->rb_left;  

  204.                 }  

  205.                 rb_set_color(other, rb_color(parent));  

  206.                 rb_set_black(parent);  

  207.                 rb_set_black(other->rb_left);  

  208.                 __rb_rotate_right(parent, root);  

  209.                 node = root->rb_node;  

  210.                 break;  

  211.             }  

  212.         }  

  213.     }  

  214.     if (node)  

  215.         rb_set_black(node);  

  216. }  

  217.   

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

  219. {  

  220.     struct rb_node *child, *parent;  

  221.     int color;  

  222.   

  223.     if (!node->rb_left)  

  224.         child = node->rb_right;  

  225.     else if (!node->rb_right)  

  226.         child = node->rb_left;  

  227.     else  

  228.     {  

  229.         struct rb_node *old = node, *left;  

  230.   

  231.         node = node->rb_right;  

  232.         while ((left = node->rb_left) != NULL)  

  233.             node = left;  

  234.   

  235.         if (rb_parent(old)) {  

  236.             if (rb_parent(old)->rb_left == old)  

  237.                 rb_parent(old)->rb_left = node;  

  238.             else  

  239.                 rb_parent(old)->rb_right = node;  

  240.         } else  

  241.             root->rb_node = node;  

  242.   

  243.         child = node->rb_right;  

  244.         parent = rb_parent(node);  

  245.         color = rb_color(node);  

  246.   

  247.         if (parent == old) {  

  248.             parent = node;  

  249.         } else {  

  250.             if (child)  

  251.                 rb_set_parent(child, parent);  

  252.             parent->rb_left = child;  

  253.   

  254.             node->rb_right = old->rb_right;  

  255.             rb_set_parent(old->rb_right, node);  

  256.         }  

  257.   

  258.         node->rb_parent_color = old->rb_parent_color;  

  259.         node->rb_left = old->rb_left;  

  260.         rb_set_parent(old->rb_left, node);  

  261.   

  262.         goto color;  

  263.     }  

  264.   

  265.     parent = rb_parent(node);  

  266.     color = rb_color(node);  

  267.   

  268.     if (child)  

  269.         rb_set_parent(child, parent);  

  270.     if (parent)  

  271.     {  

  272.         if (parent->rb_left == node)  

  273.             parent->rb_left = child;  

  274.         else  

  275.             parent->rb_right = child;  

  276.     }  

  277.     else  

  278.         root->rb_node = child;  

  279.   

  280.  color:  

  281.     if (color == RB_BLACK)  

  282.         __rb_erase_color(child, parent, root);  

  283. }  

  284. EXPORT_SYMBOL(rb_erase);  

  285.   

  286. static void rb_augment_path(struct rb_node *node, rb_augment_f func, void *data)  

  287. {  

  288.     struct rb_node *parent;  

  289.   

  290. up:  

  291.     func(node, data);  

  292.     parent = rb_parent(node);  

  293.     if (!parent)  

  294.         return;  

  295.   

  296.     if (node == parent->rb_left && parent->rb_right)  

  297.         func(parent->rb_right, data);  

  298.     else if (parent->rb_left)  

  299.         func(parent->rb_left, data);  

  300.   

  301.     node = parent;  

  302.     goto up;  

  303. }  

  304.   

  305. /* 

  306.  * after inserting @node into the tree, update the tree to account for 

  307.  * both the new_node entry and any damage done by rebalance 

  308.  */  

  309. void rb_augment_insert(struct rb_node *node, rb_augment_f func, void *data)  

  310. {  

  311.     if (node->rb_left)  

  312.         node = node->rb_left;  

  313.     else if (node->rb_right)  

  314.         node = node->rb_right;  

  315.   

  316.     rb_augment_path(node, func, data);  

  317. }  

  318. EXPORT_SYMBOL(rb_augment_insert);  

  319.   

  320. /* 

  321.  * before removing the node, find the deepest node on the rebalance path 

  322.  * that will still be there after @node gets removed 

  323.  */  

  324. struct rb_node *rb_augment_erase_begin(struct rb_node *node)  

  325. {  

  326.     struct rb_node *deepest;  

  327.   

  328.     if (!node->rb_right && !node->rb_left)  

  329.         deepest = rb_parent(node);  

  330.     else if (!node->rb_right)  

  331.         deepest = node->rb_left;  

  332.     else if (!node->rb_left)  

  333.         deepest = node->rb_right;  

  334.     else {  

  335.         deepest = rb_next(node);  

  336.         if (deepest->rb_right)  

  337.             deepest = deepest->rb_right;  

  338.         else if (rb_parent(deepest) != node)  

  339.             deepest = rb_parent(deepest);  

  340.     }  

  341.   

  342.     return deepest;  

  343. }  

  344. EXPORT_SYMBOL(rb_augment_erase_begin);  

  345.   

  346. /* 

  347.  * after removal, update the tree to account for the removed entry 

  348.  * and any rebalance damage. 

  349.  */  

  350. void rb_augment_erase_end(struct rb_node *node, rb_augment_f func, void *data)  

  351. {  

  352.     if (node)  

  353.         rb_augment_path(node, func, data);  

  354. }  

  355. EXPORT_SYMBOL(rb_augment_erase_end);  

  356.   

  357. /* 

  358.  * This function returns the first node (in sort order) of the tree. 

  359.  */  

  360. struct rb_node *rb_first(const struct rb_root *root)  

  361. {  

  362.     struct rb_node  *n;  

  363.   

  364.     n = root->rb_node;  

  365.     if (!n)  

  366.         return NULL;  

  367.     while (n->rb_left)  

  368.         n = n->rb_left;  

  369.     return n;  

  370. }  

  371. EXPORT_SYMBOL(rb_first);  

  372.   

  373. struct rb_node *rb_last(const struct rb_root *root)  

  374. {  

  375.     struct rb_node  *n;  

  376.   

  377.     n = root->rb_node;  

  378.     if (!n)  

  379.         return NULL;  

  380.     while (n->rb_right)  

  381.         n = n->rb_right;  

  382.     return n;  

  383. }  

  384. EXPORT_SYMBOL(rb_last);  

  385.   

  386. struct rb_node *rb_next(const struct rb_node *node)  

  387. {  

  388.     struct rb_node *parent;  

  389.   

  390.     if (rb_parent(node) == node)  

  391.         return NULL;  

  392.   

  393.     /* If we have a right-hand child, go down and then left as far 

  394.        as we can. */  

  395.     if (node->rb_right) {  

  396.         node = node->rb_right;   

  397.         while (node->rb_left)  

  398.             node=node->rb_left;  

  399.         return (struct rb_node *)node;  

  400.     }  

  401.   

  402.     /* No right-hand children.  Everything down and left is 

  403.        smaller than us, so any ‘next’ node must be in the general 

  404.        direction of our parent. Go up the tree; any time the 

  405.        ancestor is a right-hand child of its parent, keep going 

  406.        up. First time it’s a left-hand child of its parent, said 

  407.        parent is our ‘next’ node. */  

  408.     while ((parent = rb_parent(node)) && node == parent->rb_right)  

  409.         node = parent;  

  410.   

  411.     return parent;  

  412. }  

  413. EXPORT_SYMBOL(rb_next);  

  414.   

  415. struct rb_node *rb_prev(const struct rb_node *node)  

  416. {  

  417.     struct rb_node *parent;  

  418.   

  419.     if (rb_parent(node) == node)  

  420.         return NULL;  

  421.   

  422.     /* If we have a left-hand child, go down and then right as far 

  423.        as we can. */  

  424.     if (node->rb_left) {  

  425.         node = node->rb_left;   

  426.         while (node->rb_right)  

  427.             node=node->rb_right;  

  428.         return (struct rb_node *)node;  

  429.     }  

  430.   

  431.     /* No left-hand children. Go up till we find an ancestor which 

  432.        is a right-hand child of its parent */  

  433.     while ((parent = rb_parent(node)) && node == parent->rb_left)  

  434.         node = parent;  

  435.   

  436.     return parent;  

  437. }  

  438. EXPORT_SYMBOL(rb_prev);  

  439.   

  440. void rb_replace_node(struct rb_node *victim, struct rb_node *new_node,  

  441.              struct rb_root *root)  

  442. {  

  443.     struct rb_node *parent = rb_parent(victim);  

  444.   

  445.     /* Set the surrounding nodes to point to the replacement */  

  446.     if (parent) {  

  447.         if (victim == parent->rb_left)  

  448.             parent->rb_left = new_node;  

  449.         else  

  450.             parent->rb_right = new_node;  

  451.     } else {  

  452.         root->rb_node = new_node;  

  453.     }  

  454.     if (victim->rb_left)  

  455.         rb_set_parent(victim->rb_left, new_node);  

  456.     if (victim->rb_right)  

  457.         rb_set_parent(victim->rb_right, new_node);  

  458.   

  459.     /* Copy the pointers/colour from the victim to the replacement */  

  460.     *new_node = *victim;  

  461. }  

  462. 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:


  1. #ifndef RB_TREE_MAIN_H   

  2. #define RB_TREE_MAIN_H   

  3.   

  4. #include “rb_tree.h”   

  5.   

  6. void    my_insert(struct rb_root *root, void *ins);  

  7. int     my_cmp(void *src, void *dest);  

  8. void    my_rb_walk(const struct rb_root *root);  

  9. void    my_remove(struct rb_root *g_my_root, void *del);  

  10.   

  11. #endif  

man文件:rb_tree_main.cpp


  1. // rb_tree_main.cpp : Defines the entry point for the console application.   

  2. //   

  3. #include <string.h>   

  4. #include <stdlib.h>   

  5. #include “rb_tree.h”   

  6. #include “rb_tree_main.h”   

  7.   

  8. typedef struct my_rb  

  9. {  

  10.     int rand_val;  

  11.     struct rb_node my_rb_node;  

  12. }my_rb;  

  13.   

  14. struct rb_root g_my_root = {NULL, my_cmp, my_insert, my_remove};  

  15.   

  16. void my_insert(struct rb_root *root, void *ins)  

  17. {  

  18.     struct my_rb *iter;  

  19.     struct my_rb *src = (struct my_rb *)ins;  

  20.     struct rb_node **p = &root->rb_node;  

  21.     struct rb_node *parent = NULL;  

  22.   

  23.     if(!ins)  

  24.     {  

  25.         return;  

  26.     }  

  27.   

  28.     while (*p != NULL) {  

  29.         parent = *p;  

  30.         iter = (struct my_rb *)rb_entry(parent, struct my_rb, my_rb_node);  

  31.   

  32.         if (root->cmp(src, iter) < 0)  

  33.             p = &(*p)->rb_left;  

  34.         else  

  35.             p = &(*p)->rb_right;  

  36.     }  

  37.   

  38.     rb_link_node(&src->my_rb_node, parent, p);  

  39.     rb_insert_color(&src->my_rb_node, root);  

  40. }  

  41.   

  42. int my_cmp(void *src, void *dest)  

  43. {  

  44.     struct my_rb *my_src = (struct my_rb *)src;  

  45.     struct my_rb *my_dest = (struct my_rb *)dest;  

  46.   

  47.     if(!my_src || !my_dest)  

  48.     {  

  49.         return 0;  

  50.     }  

  51.   

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

  53.     {  

  54.         return -1;  

  55.     }  

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

  57.     {  

  58.         return 1;  

  59.     }  

  60.     else  

  61.     {  

  62.         return 0;  

  63.     }  

  64. }  

  65.   

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

  67. {  

  68.     struct my_rb    *entry      = NULL;  

  69.     struct my_rb    *del_node   = (struct my_rb *)del;  

  70.     struct rb_node  *n          = NULL;   

  71.   

  72.     if(!g_my_root || !del)  

  73.     {  

  74.         return;  

  75.     }  

  76.   

  77.     n = g_my_root->rb_node;  

  78.   

  79.     while (n)  

  80.     {  

  81.         entry = (struct my_rb *)rb_entry(n, struct my_rb, my_rb_node);  

  82.   

  83.         if (g_my_root->cmp(entry, del_node) > 0)  

  84.         {  

  85.             n = n->rb_left;  

  86.         }  

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

  88.         {  

  89.             n = n->rb_right;  

  90.         }  

  91.         else  

  92.         {  

  93.             rb_erase(n, g_my_root);  

  94.             free(entry);  

  95.             entry = NULL;  

  96.             return ;  

  97.         }  

  98.     }  

  99.   

  100.     return ;  

  101. }  

  102.   

  103.   

  104. void my_rb_walk(const struct rb_root *root)  

  105. {  

  106.     struct rb_node *temp = rb_first(root);  

  107.     struct my_rb *my_entry = NULL;  

  108.   

  109.     while(temp)  

  110.     {  

  111.         my_entry = (struct my_rb *)rb_entry(temp, my_rb, my_rb_node);  

  112.         printf(“node with rand_val %d .\n”, my_entry->rand_val);  

  113.   

  114.         temp = rb_next(temp);  

  115.     }  

  116. }  

  117.   

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

  119. {  

  120.     struct my_rb *my_rb_node = NULL;  

  121.   

  122.     struct my_rb del_node = {4, {0}};  

  123.   

  124.     for (int i = 0; i < 5; i++)  

  125.     {  

  126.         my_rb_node = (struct my_rb *)malloc(sizeof *my_rb_node);  

  127.         memset(my_rb_node, 0, sizeof *my_rb_node);  

  128.         my_rb_node->rand_val = i;  

  129.         g_my_root.insert(&g_my_root, my_rb_node);  

  130.     }  

  131.   

  132.     my_rb_walk(&g_my_root);  

  133.   

  134.     g_my_root.remove(&g_my_root, &del_node);  

  135.   

  136.     my_rb_walk(&g_my_root);  

  137.   

  138.     return 0;  

  139. }  

注意四点:


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


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


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


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


  1. unsigned long  rb_parent_color;  

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


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


  1. struct rb_node  

  2. {  

  3.     struct rb_node *rb_parent;  

  4.     int rb_color;  

  5. #define RB_RED      0   

  6. #define RB_BLACK    1   

  7.     struct rb_node *rb_right;  

  8.     struct rb_node *rb_left;  

  9. };  

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


  1. #ifndef _LP64   

  2.   

  3. struct avl_node {  

  4.     struct avl_node *avl_child[2];  /* left/right children */  

  5.     struct avl_node *avl_parent;    /* this node’s parent */  

  6.     unsigned short avl_child_index; /* my index in parent’s avl_child[] */  

  7.     short avl_balance;      /* balance value: -1, 0, +1 */  

  8. };  

  9.   

  10. #else /* _LP64 */   

  11.   

  12. /* 

  13.  * for 64 bit machines, avl_pcb contains parent pointer, balance and child_index 

  14.  * values packed in the following manner: 

  15.  * 

  16.  * |63                                  3|        2        |1          0 | 

  17.  * |————————————-|—————–|————-| 

  18.  * |      avl_parent hi order bits       | avl_child_index | avl_balance | 

  19.  * |                                     |                 |     + 1     | 

  20.  * |————————————-|—————–|————-| 

  21.  * 

  22.  */  

  23. struct avl_node {  

  24.     struct avl_node *avl_child[2];  /* left/right children nodes */  

  25.     uintptr_t avl_pcb;      /* parent, child_index, balance */  

  26. };  


  1. #endif   

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

赞(0) 打赏
转载请注明出处:服务器评测 » Linux内核的红黑树RB_TREE和FreeBSD 8.0里面的AVL_TREE比较
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏