Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrbtree.h
Go to the documentation of this file.
00001 /* 00002 * Red-black search tree support 00003 * 00004 * Copyright 2009 Henri Verbeet 00005 * Copyright 2009 Andrew Riedi 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #ifndef __WINE_WINE_RBTREE_H 00023 #define __WINE_WINE_RBTREE_H 00024 00025 #define WINE_RB_ENTRY_VALUE(element, type, field) \ 00026 ((type *)((char *)(element) - FIELD_OFFSET(type, field))) 00027 00028 struct wine_rb_entry 00029 { 00030 struct wine_rb_entry *left; 00031 struct wine_rb_entry *right; 00032 unsigned int flags; 00033 }; 00034 00035 struct wine_rb_stack 00036 { 00037 struct wine_rb_entry ***entries; 00038 size_t count; 00039 size_t size; 00040 }; 00041 00042 struct wine_rb_functions 00043 { 00044 void *(*alloc)(size_t size); 00045 void *(*realloc)(void *ptr, size_t size); 00046 void (*free)(void *ptr); 00047 int (*compare)(const void *key, const struct wine_rb_entry *entry); 00048 }; 00049 00050 struct wine_rb_tree 00051 { 00052 const struct wine_rb_functions *functions; 00053 struct wine_rb_entry *root; 00054 struct wine_rb_stack stack; 00055 }; 00056 00057 typedef void (wine_rb_traverse_func_t)(struct wine_rb_entry *entry, void *context); 00058 00059 #define WINE_RB_FLAG_RED 0x1 00060 #define WINE_RB_FLAG_STOP 0x2 00061 #define WINE_RB_FLAG_TRAVERSED_LEFT 0x4 00062 #define WINE_RB_FLAG_TRAVERSED_RIGHT 0x8 00063 00064 static inline void wine_rb_stack_clear(struct wine_rb_stack *stack) 00065 { 00066 stack->count = 0; 00067 } 00068 00069 static inline void wine_rb_stack_push(struct wine_rb_stack *stack, struct wine_rb_entry **entry) 00070 { 00071 stack->entries[stack->count++] = entry; 00072 } 00073 00074 static inline int wine_rb_ensure_stack_size(struct wine_rb_tree *tree, size_t size) 00075 { 00076 struct wine_rb_stack *stack = &tree->stack; 00077 00078 if (size > stack->size) 00079 { 00080 size_t new_size = stack->size << 1; 00081 struct wine_rb_entry ***new_entries = tree->functions->realloc(stack->entries, 00082 new_size * sizeof(*stack->entries)); 00083 00084 if (!new_entries) return -1; 00085 00086 stack->entries = new_entries; 00087 stack->size = new_size; 00088 } 00089 00090 return 0; 00091 } 00092 00093 static inline int wine_rb_is_red(struct wine_rb_entry *entry) 00094 { 00095 return entry && (entry->flags & WINE_RB_FLAG_RED); 00096 } 00097 00098 static inline void wine_rb_rotate_left(struct wine_rb_entry **entry) 00099 { 00100 struct wine_rb_entry *e = *entry; 00101 struct wine_rb_entry *right = e->right; 00102 00103 e->right = right->left; 00104 right->left = e; 00105 right->flags &= ~WINE_RB_FLAG_RED; 00106 right->flags |= e->flags & WINE_RB_FLAG_RED; 00107 e->flags |= WINE_RB_FLAG_RED; 00108 *entry = right; 00109 } 00110 00111 static inline void wine_rb_rotate_right(struct wine_rb_entry **entry) 00112 { 00113 struct wine_rb_entry *e = *entry; 00114 struct wine_rb_entry *left = e->left; 00115 00116 e->left = left->right; 00117 left->right = e; 00118 left->flags &= ~WINE_RB_FLAG_RED; 00119 left->flags |= e->flags & WINE_RB_FLAG_RED; 00120 e->flags |= WINE_RB_FLAG_RED; 00121 *entry = left; 00122 } 00123 00124 static inline void wine_rb_flip_color(struct wine_rb_entry *entry) 00125 { 00126 entry->flags ^= WINE_RB_FLAG_RED; 00127 entry->left->flags ^= WINE_RB_FLAG_RED; 00128 entry->right->flags ^= WINE_RB_FLAG_RED; 00129 } 00130 00131 static inline void wine_rb_fixup(struct wine_rb_stack *stack) 00132 { 00133 while (stack->count) 00134 { 00135 struct wine_rb_entry **entry = stack->entries[stack->count - 1]; 00136 00137 if ((*entry)->flags & WINE_RB_FLAG_STOP) 00138 { 00139 (*entry)->flags &= ~WINE_RB_FLAG_STOP; 00140 return; 00141 } 00142 00143 if (wine_rb_is_red((*entry)->right) && !wine_rb_is_red((*entry)->left)) wine_rb_rotate_left(entry); 00144 if (wine_rb_is_red((*entry)->left) && wine_rb_is_red((*entry)->left->left)) wine_rb_rotate_right(entry); 00145 if (wine_rb_is_red((*entry)->left) && wine_rb_is_red((*entry)->right)) wine_rb_flip_color(*entry); 00146 --stack->count; 00147 } 00148 } 00149 00150 static inline void wine_rb_move_red_left(struct wine_rb_entry **entry) 00151 { 00152 wine_rb_flip_color(*entry); 00153 if (wine_rb_is_red((*entry)->right->left)) 00154 { 00155 wine_rb_rotate_right(&(*entry)->right); 00156 wine_rb_rotate_left(entry); 00157 wine_rb_flip_color(*entry); 00158 } 00159 } 00160 00161 static inline void wine_rb_move_red_right(struct wine_rb_entry **entry) 00162 { 00163 wine_rb_flip_color(*entry); 00164 if (wine_rb_is_red((*entry)->left->left)) 00165 { 00166 wine_rb_rotate_right(entry); 00167 wine_rb_flip_color(*entry); 00168 } 00169 } 00170 00171 static inline void wine_rb_postorder(struct wine_rb_tree *tree, wine_rb_traverse_func_t *callback, void *context) 00172 { 00173 struct wine_rb_entry **entry; 00174 00175 if (!tree->root) return; 00176 00177 for (entry = &tree->root;;) 00178 { 00179 struct wine_rb_entry *e = *entry; 00180 00181 if (e->left && !(e->flags & WINE_RB_FLAG_TRAVERSED_LEFT)) 00182 { 00183 wine_rb_stack_push(&tree->stack, entry); 00184 e->flags |= WINE_RB_FLAG_TRAVERSED_LEFT; 00185 entry = &e->left; 00186 continue; 00187 } 00188 00189 if (e->right && !(e->flags & WINE_RB_FLAG_TRAVERSED_RIGHT)) 00190 { 00191 wine_rb_stack_push(&tree->stack, entry); 00192 e->flags |= WINE_RB_FLAG_TRAVERSED_RIGHT; 00193 entry = &e->right; 00194 continue; 00195 } 00196 00197 e->flags &= ~(WINE_RB_FLAG_TRAVERSED_LEFT | WINE_RB_FLAG_TRAVERSED_RIGHT); 00198 callback(e, context); 00199 00200 if (!tree->stack.count) break; 00201 entry = tree->stack.entries[--tree->stack.count]; 00202 } 00203 } 00204 00205 static inline int wine_rb_init(struct wine_rb_tree *tree, const struct wine_rb_functions *functions) 00206 { 00207 tree->functions = functions; 00208 tree->root = NULL; 00209 00210 tree->stack.entries = functions->alloc(16 * sizeof(*tree->stack.entries)); 00211 if (!tree->stack.entries) return -1; 00212 tree->stack.size = 16; 00213 tree->stack.count = 0; 00214 00215 return 0; 00216 } 00217 00218 static inline void wine_rb_for_each_entry(struct wine_rb_tree *tree, wine_rb_traverse_func_t *callback, void *context) 00219 { 00220 wine_rb_postorder(tree, callback, context); 00221 } 00222 00223 static inline void wine_rb_destroy(struct wine_rb_tree *tree, wine_rb_traverse_func_t *callback, void *context) 00224 { 00225 /* Note that we use postorder here because the callback will likely free the entry. */ 00226 if (callback) wine_rb_postorder(tree, callback, context); 00227 00228 tree->root = NULL; 00229 tree->functions->free(tree->stack.entries); 00230 } 00231 00232 static inline struct wine_rb_entry *wine_rb_get(const struct wine_rb_tree *tree, const void *key) 00233 { 00234 struct wine_rb_entry *entry = tree->root; 00235 while (entry) 00236 { 00237 int c = tree->functions->compare(key, entry); 00238 if (!c) return entry; 00239 entry = c < 0 ? entry->left : entry->right; 00240 } 00241 return NULL; 00242 } 00243 00244 static inline int wine_rb_put(struct wine_rb_tree *tree, const void *key, struct wine_rb_entry *entry) 00245 { 00246 struct wine_rb_entry **parent = &tree->root; 00247 size_t black_height = 1; 00248 00249 while (*parent) 00250 { 00251 int c; 00252 00253 if (!wine_rb_is_red(*parent)) ++black_height; 00254 00255 wine_rb_stack_push(&tree->stack, parent); 00256 00257 c = tree->functions->compare(key, *parent); 00258 if (!c) 00259 { 00260 wine_rb_stack_clear(&tree->stack); 00261 return -1; 00262 } 00263 else if (c < 0) parent = &(*parent)->left; 00264 else parent = &(*parent)->right; 00265 } 00266 00267 /* After insertion, the path length to any node should be <= (black_height + 1) * 2. */ 00268 if (wine_rb_ensure_stack_size(tree, black_height << 1) == -1) 00269 { 00270 wine_rb_stack_clear(&tree->stack); 00271 return -1; 00272 } 00273 00274 entry->flags = WINE_RB_FLAG_RED; 00275 entry->left = NULL; 00276 entry->right = NULL; 00277 *parent = entry; 00278 00279 wine_rb_fixup(&tree->stack); 00280 tree->root->flags &= ~WINE_RB_FLAG_RED; 00281 00282 return 0; 00283 } 00284 00285 static inline void wine_rb_remove(struct wine_rb_tree *tree, const void *key) 00286 { 00287 struct wine_rb_entry **entry = &tree->root; 00288 00289 while (*entry) 00290 { 00291 if (tree->functions->compare(key, *entry) < 0) 00292 { 00293 wine_rb_stack_push(&tree->stack, entry); 00294 if (!wine_rb_is_red((*entry)->left) && !wine_rb_is_red((*entry)->left->left)) wine_rb_move_red_left(entry); 00295 entry = &(*entry)->left; 00296 } 00297 else 00298 { 00299 if (wine_rb_is_red((*entry)->left)) wine_rb_rotate_right(entry); 00300 if (!tree->functions->compare(key, *entry) && !(*entry)->right) 00301 { 00302 *entry = NULL; 00303 break; 00304 } 00305 if (!wine_rb_is_red((*entry)->right) && !wine_rb_is_red((*entry)->right->left)) 00306 wine_rb_move_red_right(entry); 00307 if (!tree->functions->compare(key, *entry)) 00308 { 00309 struct wine_rb_entry **e = &(*entry)->right; 00310 struct wine_rb_entry *m = *e; 00311 while (m->left) m = m->left; 00312 00313 wine_rb_stack_push(&tree->stack, entry); 00314 (*entry)->flags |= WINE_RB_FLAG_STOP; 00315 00316 while ((*e)->left) 00317 { 00318 wine_rb_stack_push(&tree->stack, e); 00319 if (!wine_rb_is_red((*e)->left) && !wine_rb_is_red((*e)->left->left)) wine_rb_move_red_left(e); 00320 e = &(*e)->left; 00321 } 00322 *e = NULL; 00323 wine_rb_fixup(&tree->stack); 00324 00325 *m = **entry; 00326 *entry = m; 00327 00328 break; 00329 } 00330 else 00331 { 00332 wine_rb_stack_push(&tree->stack, entry); 00333 entry = &(*entry)->right; 00334 } 00335 } 00336 } 00337 00338 wine_rb_fixup(&tree->stack); 00339 if (tree->root) tree->root->flags &= ~WINE_RB_FLAG_RED; 00340 } 00341 00342 #endif /* __WINE_WINE_RBTREE_H */ Generated on Sat May 26 2012 04:32:08 for ReactOS by
1.7.6.1
|