Commit 16c58ab9738f91d021a8685184054c4270c32f47
1 parent
5fd8c71f
change all the rebalance code to be macros
Showing
2 changed files
with
164 additions
and
177 deletions
@@ -41,10 +41,10 @@ | @@ -41,10 +41,10 @@ | ||
41 | 41 | ||
42 | #define TR_TREE_GRANDPARENT(node) (TR_TREE_PARENT((node))->parent) | 42 | #define TR_TREE_GRANDPARENT(node) (TR_TREE_PARENT((node))->parent) |
43 | 43 | ||
44 | -#define TR_TREE_UNCLE(node) \ | ||
45 | - ((node)->parent == (node)->parent->parent->left? \ | ||
46 | - (node)->parent->parent->right: \ | ||
47 | - (node)->parent->parent->left) | 44 | +#define TR_TREE_UNCLE(node) \ |
45 | + ((node)->parent == (node)->parent->parent->left \ | ||
46 | + ? (node)->parent->parent->right \ | ||
47 | + : (node)->parent->parent->left) | ||
48 | 48 | ||
49 | #define TR_TREE_REPLACE_NODE(root, node1, node2) \ | 49 | #define TR_TREE_REPLACE_NODE(root, node1, node2) \ |
50 | if (NULL != (node1)->parent) { \ | 50 | if (NULL != (node1)->parent) { \ |
@@ -89,16 +89,21 @@ | @@ -89,16 +89,21 @@ | ||
89 | 89 | ||
90 | typedef enum {rbBlack=1, rbRed=2} TR_rbColor; | 90 | typedef enum {rbBlack=1, rbRed=2} TR_rbColor; |
91 | 91 | ||
92 | -#define TR_TREE_NODE_BLACK(node) (NULL == (node) || rbBlack == (node)->color) | ||
93 | -#define TR_TREE_NODE_RED(node) (NULL == (node) || rbRed == (node)->color) | ||
94 | -#define TR_TREE_NODE_STRICT_BLACK(node) (NULL != (node) && rbBlack == (node)->color) | ||
95 | -#define TR_TREE_NODE_STRICT_RED(node) (NULL != (node) && rbRed == (node)->color) | 92 | +#define TR_TREE_NODE_BLACK(node) \ |
93 | + (NULL == (node) || rbBlack == (node)->color) | ||
94 | +#define TR_TREE_NODE_RED(node) \ | ||
95 | + (NULL == (node) || rbRed == (node)->color) | ||
96 | +#define TR_TREE_NODE_STRICT_BLACK(node) \ | ||
97 | + (NULL != (node) && rbBlack == (node)->color) | ||
98 | +#define TR_TREE_NODE_STRICT_RED(node) \ | ||
99 | + (NULL != (node) && rbRed == (node)->color) | ||
96 | 100 | ||
97 | #define TR_TREE_INORDER_SUCC(node, succ) \ | 101 | #define TR_TREE_INORDER_SUCC(node, succ) \ |
98 | succ = (node)->right; \ | 102 | succ = (node)->right; \ |
99 | while (NULL != succ->left) { \ | 103 | while (NULL != succ->left) { \ |
100 | succ = succ->left; \ | 104 | succ = succ->left; \ |
101 | } | 105 | } |
106 | + | ||
102 | /* | 107 | /* |
103 | * Find data in a tree. | 108 | * Find data in a tree. |
104 | * Attention: This will change node, so normally you need to copy | 109 | * Attention: This will change node, so normally you need to copy |
@@ -125,6 +130,151 @@ typedef enum {rbBlack=1, rbRed=2} TR_rbColor; | @@ -125,6 +130,151 @@ typedef enum {rbBlack=1, rbRed=2} TR_rbColor; | ||
125 | } \ | 130 | } \ |
126 | } | 131 | } |
127 | 132 | ||
133 | +#define TR_TREE_BALANCE_DELETE_CASE1(node) \ | ||
134 | + if (NULL == TR_TREE_PARENT((node))) { \ | ||
135 | + break; \ | ||
136 | + } | ||
137 | + | ||
138 | +#define TR_TREE_BALANCE_DELETE_CASE2(root, node, sibling) \ | ||
139 | + if (NULL != (sibling) && rbRed == (sibling)->color) { \ | ||
140 | + (node)->parent->color = rbRed; \ | ||
141 | + (sibling)->color = rbBlack; \ | ||
142 | + if (NULL != (node)->parent->right \ | ||
143 | + && (node) != (node)->parent->right) { \ | ||
144 | + TR_TREE_ROTATE(left, (root), (node)->parent); \ | ||
145 | + } else { \ | ||
146 | + TR_TREE_ROTATE(right, (root), (node)->parent); \ | ||
147 | + } \ | ||
148 | + (sibling) = TR_TREE_SIBLING((node)); \ | ||
149 | + } | ||
150 | + | ||
151 | +#define TR_TREE_BALANCE_DELETE_CASE34(root, node, sibling) \ | ||
152 | + if (NULL == (sibling) \ | ||
153 | + || (rbBlack == (sibling)->color \ | ||
154 | + && TR_TREE_NODE_BLACK((sibling)->left) \ | ||
155 | + && TR_TREE_NODE_BLACK((sibling)->right))) { \ | ||
156 | + if (NULL != (sibling)) { \ | ||
157 | + (sibling)->color = rbRed; \ | ||
158 | + } \ | ||
159 | + if (rbBlack == (node)->parent->color) { \ | ||
160 | + (node) = (node)->parent; \ | ||
161 | + continue; \ | ||
162 | + } else { \ | ||
163 | + (node)->parent->color = rbBlack; \ | ||
164 | + break; \ | ||
165 | + } \ | ||
166 | + } | ||
167 | + | ||
168 | +/* | ||
169 | + * this if statement is trivial, | ||
170 | + * due to case 2 (even though case 2 changed the sibling to a | ||
171 | + * sibling's child, | ||
172 | + * the sibling's child can't be red, since no red parent can | ||
173 | + * have a red child). | ||
174 | + * | ||
175 | + * the following statements just force the red to be on the | ||
176 | + * left of the left of the parent, | ||
177 | + * or right of the right, so case 6 will rotate correctly. | ||
178 | + */ | ||
179 | +#define TR_TREE_BALANCE_DELETE_CASE5(root, node, sibling) \ | ||
180 | + if (NULL != (sibling) && rbBlack == (sibling)->color) { \ | ||
181 | + if ((node) == (node)->parent->left \ | ||
182 | + && TR_TREE_NODE_BLACK((sibling)->right) \ | ||
183 | + && TR_TREE_NODE_STRICT_RED((sibling)->left)) { \ | ||
184 | + (sibling)->color = rbRed; \ | ||
185 | + (sibling)->left->color = rbBlack; \ | ||
186 | + TR_TREE_ROTATE(right, (root), (sibling)); \ | ||
187 | + } else if ((node) == (node)->parent->right \ | ||
188 | + && TR_TREE_NODE_BLACK((sibling)->left) \ | ||
189 | + && TR_TREE_NODE_STRICT_RED((sibling)->right)) { \ | ||
190 | + (sibling)->color = rbRed; \ | ||
191 | + (sibling)->right->color = rbBlack; \ | ||
192 | + TR_TREE_ROTATE(left, (root), (sibling)); \ | ||
193 | + } \ | ||
194 | + (sibling) = TR_TREE_SIBLING((node)); \ | ||
195 | + } | ||
196 | + | ||
197 | +#define TR_TREE_BALANCE_DELETE_CASE6(root, node, sibling) \ | ||
198 | + if (NULL != (sibling)) { \ | ||
199 | + (sibling)->color = (node)->parent->color; \ | ||
200 | + } \ | ||
201 | + if (NULL != (node) && NULL != (node)->parent) { \ | ||
202 | + (node)->parent->color = rbBlack; \ | ||
203 | + if (NULL != (node)->parent->right \ | ||
204 | + && (node) != (node)->parent->right) { \ | ||
205 | + if (NULL != (sibling)->right) { \ | ||
206 | + (sibling)->right->color = rbBlack; \ | ||
207 | + } \ | ||
208 | + TR_TREE_ROTATE(left, (root), (node)->parent); \ | ||
209 | + } else { \ | ||
210 | + if (NULL != (sibling)->left) { \ | ||
211 | + (sibling)->left->color = rbBlack; \ | ||
212 | + } \ | ||
213 | + TR_TREE_ROTATE(right, (root), (node)->parent); \ | ||
214 | + } \ | ||
215 | + } | ||
216 | + | ||
217 | +#define TR_TREE_BALANCE_DELETE(root, node, sibling) \ | ||
218 | + while(1) { \ | ||
219 | + TR_TREE_BALANCE_DELETE_CASE1((node)) \ | ||
220 | + TR_TREE_BALANCE_DELETE_CASE2((root), (node), (sibling)) \ | ||
221 | + TR_TREE_BALANCE_DELETE_CASE34((root), (node), (sibling)) \ | ||
222 | + TR_TREE_BALANCE_DELETE_CASE5((root), (node), (sibling)) \ | ||
223 | + TR_TREE_BALANCE_DELETE_CASE6((root), (node), (sibling)) \ | ||
224 | + break; \ | ||
225 | + } | ||
226 | + | ||
227 | +#define TR_TREE_BALANCE_INSERT_CASE1(node) \ | ||
228 | + if (NULL == TR_TREE_PARENT((node))) { \ | ||
229 | + (node)->color = rbBlack; \ | ||
230 | + break; \ | ||
231 | + } | ||
232 | + | ||
233 | +#define TR_TREE_BALANCE_INSERT_CASE2(node) \ | ||
234 | + if (rbBlack == (node)->parent->color) { \ | ||
235 | + break; \ | ||
236 | + } | ||
237 | + | ||
238 | +#define TR_TREE_BALANCE_INSERT_CASE3(node) \ | ||
239 | + if (NULL != TR_TREE_UNCLE(node) \ | ||
240 | + && rbRed == TR_TREE_UNCLE(node)->color) { \ | ||
241 | + (node)->parent->color = rbBlack; \ | ||
242 | + TR_TREE_UNCLE(node)->color = rbBlack; \ | ||
243 | + (node)->parent->parent->color = rbRed; \ | ||
244 | + (node) = (node)->parent->parent; \ | ||
245 | + continue; \ | ||
246 | + } | ||
247 | + | ||
248 | +#define TR_TREE_BALANCE_INSERT_CASE4(root, node) \ | ||
249 | + if ((node) == (node)->parent->right \ | ||
250 | + && (node)->parent == (node)->parent->parent->left) { \ | ||
251 | + TR_TREE_ROTATE(left, (root), (node)->parent); \ | ||
252 | + (node) = (node)->left; \ | ||
253 | + } else if ((node) == (node)->parent->left \ | ||
254 | + && (node)->parent == (node)->parent->parent->right) { \ | ||
255 | + TR_TREE_ROTATE(right, (root), (node)->parent); \ | ||
256 | + (node) = (node)->right; \ | ||
257 | + } | ||
258 | + | ||
259 | +#define TR_TREE_BALANCE_INSERT_CASE5(root, node) \ | ||
260 | + (node)->parent->color = rbBlack; \ | ||
261 | + (node)->parent->parent->color = rbRed; \ | ||
262 | + if ((node) == (node)->parent->left) { \ | ||
263 | + TR_TREE_ROTATE(right, (root), (node)->parent->parent); \ | ||
264 | + } else { \ | ||
265 | + TR_TREE_ROTATE(left, (root), (node)->parent->parent); \ | ||
266 | + } | ||
267 | + | ||
268 | +#define TR_TREE_BALANCE_INSERT(root, node) \ | ||
269 | + while (1) { \ | ||
270 | + TR_TREE_BALANCE_INSERT_CASE1((node)) \ | ||
271 | + TR_TREE_BALANCE_INSERT_CASE2((node)) \ | ||
272 | + TR_TREE_BALANCE_INSERT_CASE3((node)) \ | ||
273 | + TR_TREE_BALANCE_INSERT_CASE4((root), (node)) \ | ||
274 | + TR_TREE_BALANCE_INSERT_CASE5((root), (node)) \ | ||
275 | + break; \ | ||
276 | + } | ||
277 | + | ||
128 | #endif // __TR_TREE_MACROS_H__ | 278 | #endif // __TR_TREE_MACROS_H__ |
129 | 279 | ||
130 | // vim: set ts=4 sw=4: | 280 | // vim: set ts=4 sw=4: |
@@ -131,8 +131,6 @@ insertElement(struct memSegment ** tree, struct memSegment * element) | @@ -131,8 +131,6 @@ insertElement(struct memSegment ** tree, struct memSegment * element) | ||
131 | { | 131 | { |
132 | struct memSegment * node = *tree; | 132 | struct memSegment * node = *tree; |
133 | struct memSegment * new_node = NULL; | 133 | struct memSegment * new_node = NULL; |
134 | - struct memSegment * u; | ||
135 | - struct memSegment * g; | ||
136 | int found; | 134 | int found; |
137 | 135 | ||
138 | element->next = NULL; | 136 | element->next = NULL; |
@@ -173,63 +171,10 @@ insertElement(struct memSegment ** tree, struct memSegment * element) | @@ -173,63 +171,10 @@ insertElement(struct memSegment ** tree, struct memSegment * element) | ||
173 | } | 171 | } |
174 | } | 172 | } |
175 | 173 | ||
176 | - if (NULL != new_node) { | ||
177 | - /* | ||
178 | - * handle reballancing rb style | ||
179 | - */ | ||
180 | - while (1) { | ||
181 | - // case 1 | ||
182 | - if (node->parent == NULL) { | ||
183 | - node->color = rbBlack; | ||
184 | - // we're done.... :) | ||
185 | - break; | ||
186 | - } | ||
187 | - | ||
188 | - // case 2 | ||
189 | - if (node->parent->color == rbBlack) { | ||
190 | - // Tree is still valid ... wow, again we're done... :) | ||
191 | - break; | ||
192 | - } | ||
193 | - | ||
194 | - // case 3 | ||
195 | - u = TR_TREE_UNCLE(node); | ||
196 | - g = TR_TREE_GRANDPARENT(node); | ||
197 | - | ||
198 | - if (u != NULL && u->color == rbRed) { | ||
199 | - node->parent->color = rbBlack; | ||
200 | - u->color = rbBlack; | ||
201 | - g->color = rbRed; | ||
202 | - | ||
203 | - node = g; | ||
204 | - continue; | ||
205 | - } | ||
206 | - | ||
207 | - // case 4 | ||
208 | - if (node == node->parent->right && node->parent == g->left) { | ||
209 | - TR_TREE_ROTATE(left, tree, node->parent); | ||
210 | - node = node->left; | ||
211 | - } else if (node == node->parent->left && node->parent == g->right) { | ||
212 | - | ||
213 | - TR_TREE_ROTATE(right, tree, node->parent); | ||
214 | - node = node->right; | ||
215 | - } | ||
216 | - | ||
217 | - // case 5 | ||
218 | - g = TR_TREE_GRANDPARENT(node); | ||
219 | - | ||
220 | - node->parent->color = rbBlack; | ||
221 | - g->color = rbRed; | ||
222 | - | ||
223 | - if (node == node->parent->left) { | ||
224 | - TR_TREE_ROTATE(right, tree, g); | ||
225 | - } else { | ||
226 | - TR_TREE_ROTATE(left, tree, g); | ||
227 | - } | ||
228 | - | ||
229 | - // we're done.. | ||
230 | - break; | ||
231 | - } | ||
232 | - } | 174 | + /* |
175 | + * handle reballancing rb style | ||
176 | + */ | ||
177 | + TR_TREE_BALANCE_INSERT(tree, node); | ||
233 | 178 | ||
234 | return new_node; | 179 | return new_node; |
235 | } | 180 | } |
@@ -345,116 +290,8 @@ deleteElement(struct memSegment ** tree, size_t size) | @@ -345,116 +290,8 @@ deleteElement(struct memSegment ** tree, size_t size) | ||
345 | return del_node; | 290 | return del_node; |
346 | } | 291 | } |
347 | 292 | ||
348 | - // delete and rb rebalance... | ||
349 | - while(1) { | ||
350 | - // case 1 | ||
351 | - if (NULL == node->parent) { | ||
352 | - // done again | ||
353 | - break; | ||
354 | - } | ||
355 | - | ||
356 | - // case 2 | ||
357 | - s = TR_TREE_SIBLING(node); | ||
358 | - | ||
359 | - if (NULL != s && s->color == rbRed) { | ||
360 | - node->parent->color = rbRed; | ||
361 | - s->color = rbBlack; | ||
362 | - | ||
363 | - /* | ||
364 | - * detect which child we are...assumption | ||
365 | - * if we are not parent->right and parent->right is not | ||
366 | - * null we must be left, even if its set to NULL previously | ||
367 | - */ | ||
368 | - if (NULL != node->parent->right && node != node->parent->right) { | ||
369 | - TR_TREE_ROTATE(left, tree, node->parent); | ||
370 | - } else { | ||
371 | - TR_TREE_ROTATE(right, tree, node->parent); | ||
372 | - } | ||
373 | - } | ||
374 | - | ||
375 | - s = TR_TREE_SIBLING(node); | ||
376 | - // case 3 / 4 | ||
377 | - if (NULL == s || ((s->color == rbBlack) && | ||
378 | - (NULL == s->left || s->left->color == rbBlack) && | ||
379 | - (NULL == s->right || s->right->color == rbBlack))) { | ||
380 | - | ||
381 | - if (NULL != s) { | ||
382 | - s->color = rbRed; | ||
383 | - } | ||
384 | - | ||
385 | - if (node->parent->color == rbBlack) { | ||
386 | - // case 3 | ||
387 | - node = node->parent; | ||
388 | - continue; | ||
389 | - } else { | ||
390 | - // case 4 | ||
391 | - node->parent->color = rbBlack; | ||
392 | - // and done again... | ||
393 | - break; | ||
394 | - } | ||
395 | - } | ||
396 | - | ||
397 | - // case 5 | ||
398 | - if (NULL != s && s->color == rbBlack) { | ||
399 | - // this if statement is trivial, | ||
400 | - // due to case 2 (even though case 2 changed the sibling to a | ||
401 | - // sibling's child, | ||
402 | - // the sibling's child can't be red, since no red parent can | ||
403 | - // have a red child). | ||
404 | - // | ||
405 | - // the following statements just force the red to be on the | ||
406 | - // left of the left of the parent, | ||
407 | - // or right of the right, so case 6 will rotate correctly. | ||
408 | - if ((node == node->parent->left) && | ||
409 | - (NULL == s->right || s->right->color == rbBlack) && | ||
410 | - (NULL != s->left && s->left->color == rbRed)) { | ||
411 | - | ||
412 | - // this last test is trivial too due to cases 2-4. | ||
413 | - s->color = rbRed; | ||
414 | - s->left->color = rbBlack; | ||
415 | - | ||
416 | - TR_TREE_ROTATE(right, tree, s); | ||
417 | - } else if ((node == node->parent->right) && | ||
418 | - (NULL == s->left || s->left->color == rbBlack) && | ||
419 | - (NULL != s->right && s->right->color == rbRed)) { | ||
420 | - // this last test is trivial too due to cases 2-4. | ||
421 | - s->color = rbRed; | ||
422 | - s->right->color = rbBlack; | ||
423 | - | ||
424 | - TR_TREE_ROTATE(left, tree, s); | ||
425 | - } | ||
426 | - } | ||
427 | - | ||
428 | - s = TR_TREE_SIBLING(node); | ||
429 | - // case 6 | ||
430 | - if (NULL != s) { | ||
431 | - s->color = node->parent->color; | ||
432 | - } | ||
433 | - | ||
434 | - if (NULL != node && NULL != node->parent) { | ||
435 | - node->parent->color = rbBlack; | ||
436 | - | ||
437 | - /* | ||
438 | - * detect which child we are...assumption | ||
439 | - * if we are not parent->right and parent->right is not | ||
440 | - * null we must be left, even if its set to NULL previously | ||
441 | - */ | ||
442 | - if (NULL != node->parent->right && node != node->parent->right) { | ||
443 | - if (NULL != s->right) { | ||
444 | - s->right->color = rbBlack; | ||
445 | - } | ||
446 | - TR_TREE_ROTATE(left, tree, node->parent); | ||
447 | - } else { | ||
448 | - if (NULL != s->left) { | ||
449 | - s->left->color = rbBlack; | ||
450 | - } | ||
451 | - TR_TREE_ROTATE(right, tree, node->parent); | ||
452 | - } | ||
453 | - } | ||
454 | - | ||
455 | - // done... | ||
456 | - break; | ||
457 | - } | 293 | + s = TR_TREE_SIBLING(node); |
294 | + TR_TREE_BALANCE_DELETE(tree, node, s); | ||
458 | 295 | ||
459 | return del_node; | 296 | return del_node; |
460 | } | 297 | } |
Please
register
or
login
to post a comment