歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> Linux內核的紅黑樹RB_TREE和FreeBSD 8.0裡面的AVL_TREE比較

Linux內核的紅黑樹RB_TREE和FreeBSD 8.0裡面的AVL_TREE比較

日期:2017/2/28 16:08:36   编辑:Linux內核

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. #ifndef container_of
  3. /**
  4. * container_of - cast a member of a structure out to the containing structure
  5. * @ptr: the pointer to the member.
  6. * @type: the type of the container struct this is embedded in.
  7. * @member: the name of the member within the struct.
  8. *
  9. */
  10. #define container_of(ptr, type, member) ({ \
  11. const typeof(((type *)0)->member) * __mptr = (ptr); \
  12. (type *)((char *)__mptr - offsetof(type, member)); })
  13. #endif
  14. #ifndef offsetof
  15. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
  16. #endif

修改如下:

  1. #ifndef offsetof
  2. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
  3. #endif
  4. #ifndef container_of
  5. /**
  6. * container_of - cast a member of a structure out to the containing structure
  7. * @ptr: the pointer to the member.
  8. * @type: the type of the container struct this is embedded in.
  9. * @member: the name of the member within the struct.
  10. *
  11. * !!! modify the typeof marco, just use the rb_node
  12. */
  13. #define container_of(ptr, type, member) \
  14. (((char *)ptr) - offsetof(type, member))
  15. #endif
  16. #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 <[email protected]>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. linux/include/linux/rbtree.h
  16. To use rbtrees you'll have to implement your own insert and search cores.
  17. This will avoid us to use callbacks and to drop drammatically performances.
  18. I know it's not the cleaner way, but in C (not in C++) to get
  19. performances and genericity...
  20. Some example of insert and search follows here. The search is a plain
  21. normal search over an ordered tree. The insert instead must be implemented
  22. in two steps: First, the code must insert the element in order as a red leaf
  23. in the tree, and then the support library function rb_insert_color() must
  24. be called. Such function will do the not trivial work to rebalance the
  25. rbtree, if necessary.
  26. -----------------------------------------------------------------------
  27. static inline struct page * rb_search_page_cache(struct inode * inode,
  28. unsigned long offset)
  29. {
  30. struct rb_node * n = inode->i_rb_page_cache.rb_node;
  31. struct page * page;
  32. while (n)
  33. {
  34. page = rb_entry(n, struct page, rb_page_cache);
  35. if (offset < page->offset)
  36. n = n->rb_left;
  37. else if (offset > page->offset)
  38. n = n->rb_right;
  39. else
  40. return page;
  41. }
  42. return NULL;
  43. }
  44. static inline struct page * __rb_insert_page_cache(struct inode * inode,
  45. unsigned long offset,
  46. struct rb_node * node)
  47. {
  48. struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
  49. struct rb_node * parent = NULL;
  50. struct page * page;
  51. while (*p)
  52. {
  53. parent = *p;
  54. page = rb_entry(parent, struct page, rb_page_cache);
  55. if (offset < page->offset)
  56. p = &(*p)->rb_left;
  57. else if (offset > page->offset)
  58. p = &(*p)->rb_right;
  59. else
  60. return page;
  61. }
  62. rb_link_node(node, parent, p);
  63. return NULL;
  64. }
  65. static inline struct page * rb_insert_page_cache(struct inode * inode,
  66. unsigned long offset,
  67. struct rb_node * node)
  68. {
  69. struct page * ret;
  70. if ((ret = __rb_insert_page_cache(inode, offset, node)))
  71. goto out;
  72. rb_insert_color(node, &inode->i_rb_page_cache);
  73. out:
  74. return ret;
  75. }
  76. -----------------------------------------------------------------------
  77. */
  78. #ifndef _LINUX_RBTREE_H
  79. #define _LINUX_RBTREE_H
  80. #define EXPORT_SYMBOL(i)
  81. #pragma pack (push)
  82. #pragma pack(4)
  83. struct rb_node
  84. {
  85. unsigned long rb_parent_color;
  86. #define RB_RED 0
  87. #define RB_BLACK 1
  88. struct rb_node *rb_right;
  89. struct rb_node *rb_left;
  90. } ;
  91. #pragma pack (pop)
  92. /* The alignment might seem pointless, but allegedly CRIS needs it */
  93. struct rb_root
  94. {
  95. struct rb_node *rb_node;
  96. int (*cmp)(void *src, void *dst);
  97. void (*insert)(struct rb_root *root, void *ins);
  98. void (*remove)(struct rb_root *root, void *del);
  99. };
  100. #define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
  101. #define rb_color(r) ((r)->rb_parent_color & 1)
  102. #define rb_is_red(r) (!rb_color(r))
  103. #define rb_is_black(r) rb_color(r)
  104. #define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
  105. #define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
  106. static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
  107. {
  108. rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
  109. }
  110. static inline void rb_set_color(struct rb_node *rb, int color)
  111. {
  112. rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
  113. }
  114. #ifndef offsetof
  115. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
  116. #endif
  117. #ifndef container_of
  118. /**
  119. * container_of - cast a member of a structure out to the containing structure
  120. * @ptr: the pointer to the member.
  121. * @type: the type of the container struct this is embedded in.
  122. * @member: the name of the member within the struct.
  123. *
  124. * !!! modify the typeof marco, just use the rb_node
  125. */
  126. #define container_of(ptr, type, member) \
  127. (((char *)ptr) - offsetof(type, member))
  128. #endif
  129. #define RB_ROOT (struct rb_root) { NULL, }
  130. #define rb_entry(ptr, type, member) container_of(ptr, type, member)
  131. #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
  132. #define RB_EMPTY_NODE(node) (rb_parent(node) == node)
  133. #define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
  134. static inline void rb_init_node(struct rb_node *rb)
  135. {
  136. rb->rb_parent_color = 0;
  137. rb->rb_right = NULL;
  138. rb->rb_left = NULL;
  139. RB_CLEAR_NODE(rb);
  140. }
  141. extern void rb_insert_color(struct rb_node *, struct rb_root *);
  142. extern void rb_erase(struct rb_node *, struct rb_root *);
  143. typedef void (*rb_augment_f)(struct rb_node *node, void *data);
  144. extern void rb_augment_insert(struct rb_node *node,
  145. rb_augment_f func, void *data);
  146. extern struct rb_node *rb_augment_erase_begin(struct rb_node *node);
  147. extern void rb_augment_erase_end(struct rb_node *node,
  148. rb_augment_f func, void *data);
  149. /* Find logical next and previous nodes in a tree */
  150. extern struct rb_node *rb_next(const struct rb_node *);
  151. extern struct rb_node *rb_prev(const struct rb_node *);
  152. extern struct rb_node *rb_first(const struct rb_root *);
  153. extern struct rb_node *rb_last(const struct rb_root *);
  154. /* Fast replacement of a single node without remove/rebalance/add/rebalance */
  155. extern void rb_replace_node(struct rb_node *victim, struct rb_node *new_node_node,
  156. struct rb_root *root);
  157. static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
  158. struct rb_node ** rb_link)
  159. {
  160. node->rb_parent_color = (unsigned long )parent;
  161. node->rb_left = node->rb_right = NULL;
  162. *rb_link = node;
  163. }
  164. #endif /* _LINUX_RBTREE_H */
Copyright © Linux教程網 All Rights Reserved