Commit 16c58ab9738f91d021a8685184054c4270c32f47

Authored by Georg Hopp
1 parent 5fd8c71f

change all the rebalance code to be macros

... ... @@ -41,10 +41,10 @@
41 41
42 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 49 #define TR_TREE_REPLACE_NODE(root, node1, node2) \
50 50 if (NULL != (node1)->parent) { \
... ... @@ -89,16 +89,21 @@
89 89
90 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 101 #define TR_TREE_INORDER_SUCC(node, succ) \
98 102 succ = (node)->right; \
99 103 while (NULL != succ->left) { \
100 104 succ = succ->left; \
101 105 }
  106 +
102 107 /*
103 108 * Find data in a tree.
104 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 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 278 #endif // __TR_TREE_MACROS_H__
129 279
130 280 // vim: set ts=4 sw=4:
... ...
... ... @@ -131,8 +131,6 @@ insertElement(struct memSegment ** tree, struct memSegment * element)
131 131 {
132 132 struct memSegment * node = *tree;
133 133 struct memSegment * new_node = NULL;
134   - struct memSegment * u;
135   - struct memSegment * g;
136 134 int found;
137 135
138 136 element->next = NULL;
... ... @@ -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 179 return new_node;
235 180 }
... ... @@ -345,116 +290,8 @@ deleteElement(struct memSegment ** tree, size_t size)
345 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 296 return del_node;
460 297 }
... ...
Please register or login to post a comment