Browse Source

change all the rebalance code to be macros

1.0.2
Georg Hopp 12 years ago
parent
commit
16c58ab973
  1. 166
      include/tr/tree_macros.h
  2. 175
      src/memory.c

166
include/tr/tree_macros.h

@ -41,10 +41,10 @@
#define TR_TREE_GRANDPARENT(node) (TR_TREE_PARENT((node))->parent) #define TR_TREE_GRANDPARENT(node) (TR_TREE_PARENT((node))->parent)
#define TR_TREE_UNCLE(node) \
((node)->parent == (node)->parent->parent->left? \
(node)->parent->parent->right: \
(node)->parent->parent->left)
#define TR_TREE_UNCLE(node) \
((node)->parent == (node)->parent->parent->left \
? (node)->parent->parent->right \
: (node)->parent->parent->left)
#define TR_TREE_REPLACE_NODE(root, node1, node2) \ #define TR_TREE_REPLACE_NODE(root, node1, node2) \
if (NULL != (node1)->parent) { \ if (NULL != (node1)->parent) { \
@ -89,16 +89,21 @@
typedef enum {rbBlack=1, rbRed=2} TR_rbColor; typedef enum {rbBlack=1, rbRed=2} TR_rbColor;
#define TR_TREE_NODE_BLACK(node) (NULL == (node) || rbBlack == (node)->color)
#define TR_TREE_NODE_RED(node) (NULL == (node) || rbRed == (node)->color)
#define TR_TREE_NODE_STRICT_BLACK(node) (NULL != (node) && rbBlack == (node)->color)
#define TR_TREE_NODE_STRICT_RED(node) (NULL != (node) && rbRed == (node)->color)
#define TR_TREE_NODE_BLACK(node) \
(NULL == (node) || rbBlack == (node)->color)
#define TR_TREE_NODE_RED(node) \
(NULL == (node) || rbRed == (node)->color)
#define TR_TREE_NODE_STRICT_BLACK(node) \
(NULL != (node) && rbBlack == (node)->color)
#define TR_TREE_NODE_STRICT_RED(node) \
(NULL != (node) && rbRed == (node)->color)
#define TR_TREE_INORDER_SUCC(node, succ) \ #define TR_TREE_INORDER_SUCC(node, succ) \
succ = (node)->right; \ succ = (node)->right; \
while (NULL != succ->left) { \ while (NULL != succ->left) { \
succ = succ->left; \ succ = succ->left; \
} }
/* /*
* Find data in a tree. * Find data in a tree.
* Attention: This will change node, so normally you need to copy * Attention: This will change node, so normally you need to copy
@ -125,6 +130,151 @@ typedef enum {rbBlack=1, rbRed=2} TR_rbColor;
} \ } \
} }
#define TR_TREE_BALANCE_DELETE_CASE1(node) \
if (NULL == TR_TREE_PARENT((node))) { \
break; \
}
#define TR_TREE_BALANCE_DELETE_CASE2(root, node, sibling) \
if (NULL != (sibling) && rbRed == (sibling)->color) { \
(node)->parent->color = rbRed; \
(sibling)->color = rbBlack; \
if (NULL != (node)->parent->right \
&& (node) != (node)->parent->right) { \
TR_TREE_ROTATE(left, (root), (node)->parent); \
} else { \
TR_TREE_ROTATE(right, (root), (node)->parent); \
} \
(sibling) = TR_TREE_SIBLING((node)); \
}
#define TR_TREE_BALANCE_DELETE_CASE34(root, node, sibling) \
if (NULL == (sibling) \
|| (rbBlack == (sibling)->color \
&& TR_TREE_NODE_BLACK((sibling)->left) \
&& TR_TREE_NODE_BLACK((sibling)->right))) { \
if (NULL != (sibling)) { \
(sibling)->color = rbRed; \
} \
if (rbBlack == (node)->parent->color) { \
(node) = (node)->parent; \
continue; \
} else { \
(node)->parent->color = rbBlack; \
break; \
} \
}
/*
* this if statement is trivial,
* due to case 2 (even though case 2 changed the sibling to a
* sibling's child,
* the sibling's child can't be red, since no red parent can
* have a red child).
*
* the following statements just force the red to be on the
* left of the left of the parent,
* or right of the right, so case 6 will rotate correctly.
*/
#define TR_TREE_BALANCE_DELETE_CASE5(root, node, sibling) \
if (NULL != (sibling) && rbBlack == (sibling)->color) { \
if ((node) == (node)->parent->left \
&& TR_TREE_NODE_BLACK((sibling)->right) \
&& TR_TREE_NODE_STRICT_RED((sibling)->left)) { \
(sibling)->color = rbRed; \
(sibling)->left->color = rbBlack; \
TR_TREE_ROTATE(right, (root), (sibling)); \
} else if ((node) == (node)->parent->right \
&& TR_TREE_NODE_BLACK((sibling)->left) \
&& TR_TREE_NODE_STRICT_RED((sibling)->right)) { \
(sibling)->color = rbRed; \
(sibling)->right->color = rbBlack; \
TR_TREE_ROTATE(left, (root), (sibling)); \
} \
(sibling) = TR_TREE_SIBLING((node)); \
}
#define TR_TREE_BALANCE_DELETE_CASE6(root, node, sibling) \
if (NULL != (sibling)) { \
(sibling)->color = (node)->parent->color; \
} \
if (NULL != (node) && NULL != (node)->parent) { \
(node)->parent->color = rbBlack; \
if (NULL != (node)->parent->right \
&& (node) != (node)->parent->right) { \
if (NULL != (sibling)->right) { \
(sibling)->right->color = rbBlack; \
} \
TR_TREE_ROTATE(left, (root), (node)->parent); \
} else { \
if (NULL != (sibling)->left) { \
(sibling)->left->color = rbBlack; \
} \
TR_TREE_ROTATE(right, (root), (node)->parent); \
} \
}
#define TR_TREE_BALANCE_DELETE(root, node, sibling) \
while(1) { \
TR_TREE_BALANCE_DELETE_CASE1((node)) \
TR_TREE_BALANCE_DELETE_CASE2((root), (node), (sibling)) \
TR_TREE_BALANCE_DELETE_CASE34((root), (node), (sibling)) \
TR_TREE_BALANCE_DELETE_CASE5((root), (node), (sibling)) \
TR_TREE_BALANCE_DELETE_CASE6((root), (node), (sibling)) \
break; \
}
#define TR_TREE_BALANCE_INSERT_CASE1(node) \
if (NULL == TR_TREE_PARENT((node))) { \
(node)->color = rbBlack; \
break; \
}
#define TR_TREE_BALANCE_INSERT_CASE2(node) \
if (rbBlack == (node)->parent->color) { \
break; \
}
#define TR_TREE_BALANCE_INSERT_CASE3(node) \
if (NULL != TR_TREE_UNCLE(node) \
&& rbRed == TR_TREE_UNCLE(node)->color) { \
(node)->parent->color = rbBlack; \
TR_TREE_UNCLE(node)->color = rbBlack; \
(node)->parent->parent->color = rbRed; \
(node) = (node)->parent->parent; \
continue; \
}
#define TR_TREE_BALANCE_INSERT_CASE4(root, node) \
if ((node) == (node)->parent->right \
&& (node)->parent == (node)->parent->parent->left) { \
TR_TREE_ROTATE(left, (root), (node)->parent); \
(node) = (node)->left; \
} else if ((node) == (node)->parent->left \
&& (node)->parent == (node)->parent->parent->right) { \
TR_TREE_ROTATE(right, (root), (node)->parent); \
(node) = (node)->right; \
}
#define TR_TREE_BALANCE_INSERT_CASE5(root, node) \
(node)->parent->color = rbBlack; \
(node)->parent->parent->color = rbRed; \
if ((node) == (node)->parent->left) { \
TR_TREE_ROTATE(right, (root), (node)->parent->parent); \
} else { \
TR_TREE_ROTATE(left, (root), (node)->parent->parent); \
}
#define TR_TREE_BALANCE_INSERT(root, node) \
while (1) { \
TR_TREE_BALANCE_INSERT_CASE1((node)) \
TR_TREE_BALANCE_INSERT_CASE2((node)) \
TR_TREE_BALANCE_INSERT_CASE3((node)) \
TR_TREE_BALANCE_INSERT_CASE4((root), (node)) \
TR_TREE_BALANCE_INSERT_CASE5((root), (node)) \
break; \
}
#endif // __TR_TREE_MACROS_H__ #endif // __TR_TREE_MACROS_H__
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

175
src/memory.c

@ -131,8 +131,6 @@ insertElement(struct memSegment ** tree, struct memSegment * element)
{ {
struct memSegment * node = *tree; struct memSegment * node = *tree;
struct memSegment * new_node = NULL; struct memSegment * new_node = NULL;
struct memSegment * u;
struct memSegment * g;
int found; int found;
element->next = NULL; element->next = NULL;
@ -173,63 +171,10 @@ insertElement(struct memSegment ** tree, struct memSegment * element)
} }
} }
if (NULL != new_node) {
/*
* handle reballancing rb style
*/
while (1) {
// case 1
if (node->parent == NULL) {
node->color = rbBlack;
// we're done.... :)
break;
}
// case 2
if (node->parent->color == rbBlack) {
// Tree is still valid ... wow, again we're done... :)
break;
}
// case 3
u = TR_TREE_UNCLE(node);
g = TR_TREE_GRANDPARENT(node);
if (u != NULL && u->color == rbRed) {
node->parent->color = rbBlack;
u->color = rbBlack;
g->color = rbRed;
node = g;
continue;
}
// case 4
if (node == node->parent->right && node->parent == g->left) {
TR_TREE_ROTATE(left, tree, node->parent);
node = node->left;
} else if (node == node->parent->left && node->parent == g->right) {
TR_TREE_ROTATE(right, tree, node->parent);
node = node->right;
}
// case 5
g = TR_TREE_GRANDPARENT(node);
node->parent->color = rbBlack;
g->color = rbRed;
if (node == node->parent->left) {
TR_TREE_ROTATE(right, tree, g);
} else {
TR_TREE_ROTATE(left, tree, g);
}
// we're done..
break;
}
}
/*
* handle reballancing rb style
*/
TR_TREE_BALANCE_INSERT(tree, node);
return new_node; return new_node;
} }
@ -345,116 +290,8 @@ deleteElement(struct memSegment ** tree, size_t size)
return del_node; return del_node;
} }
// delete and rb rebalance...
while(1) {
// case 1
if (NULL == node->parent) {
// done again
break;
}
// case 2
s = TR_TREE_SIBLING(node);
if (NULL != s && s->color == rbRed) {
node->parent->color = rbRed;
s->color = rbBlack;
/*
* detect which child we are...assumption
* if we are not parent->right and parent->right is not
* null we must be left, even if its set to NULL previously
*/
if (NULL != node->parent->right && node != node->parent->right) {
TR_TREE_ROTATE(left, tree, node->parent);
} else {
TR_TREE_ROTATE(right, tree, node->parent);
}
}
s = TR_TREE_SIBLING(node);
// case 3 / 4
if (NULL == s || ((s->color == rbBlack) &&
(NULL == s->left || s->left->color == rbBlack) &&
(NULL == s->right || s->right->color == rbBlack))) {
if (NULL != s) {
s->color = rbRed;
}
if (node->parent->color == rbBlack) {
// case 3
node = node->parent;
continue;
} else {
// case 4
node->parent->color = rbBlack;
// and done again...
break;
}
}
// case 5
if (NULL != s && s->color == rbBlack) {
// this if statement is trivial,
// due to case 2 (even though case 2 changed the sibling to a
// sibling's child,
// the sibling's child can't be red, since no red parent can
// have a red child).
//
// the following statements just force the red to be on the
// left of the left of the parent,
// or right of the right, so case 6 will rotate correctly.
if ((node == node->parent->left) &&
(NULL == s->right || s->right->color == rbBlack) &&
(NULL != s->left && s->left->color == rbRed)) {
// this last test is trivial too due to cases 2-4.
s->color = rbRed;
s->left->color = rbBlack;
TR_TREE_ROTATE(right, tree, s);
} else if ((node == node->parent->right) &&
(NULL == s->left || s->left->color == rbBlack) &&
(NULL != s->right && s->right->color == rbRed)) {
// this last test is trivial too due to cases 2-4.
s->color = rbRed;
s->right->color = rbBlack;
TR_TREE_ROTATE(left, tree, s);
}
}
s = TR_TREE_SIBLING(node);
// case 6
if (NULL != s) {
s->color = node->parent->color;
}
if (NULL != node && NULL != node->parent) {
node->parent->color = rbBlack;
/*
* detect which child we are...assumption
* if we are not parent->right and parent->right is not
* null we must be left, even if its set to NULL previously
*/
if (NULL != node->parent->right && node != node->parent->right) {
if (NULL != s->right) {
s->right->color = rbBlack;
}
TR_TREE_ROTATE(left, tree, node->parent);
} else {
if (NULL != s->left) {
s->left->color = rbBlack;
}
TR_TREE_ROTATE(right, tree, node->parent);
}
}
// done...
break;
}
s = TR_TREE_SIBLING(node);
TR_TREE_BALANCE_DELETE(tree, node, s);
return del_node; return del_node;
} }

Loading…
Cancel
Save