Red-black tree in C











up vote
7
down vote

favorite












I would like to verify that the code fulfills the specification of a red-black tree or receive suggestions for improvements.



#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <time.h>


static char BLACK = 'b';
static char RED = 'r';

struct node {
int key;
char color;
struct node *left, *right, *parent;
};

void insert_repair_tree(struct node *n);

void delete_case1(struct node *n);

void delete_case2(struct node *n);

void delete_case3(struct node *n);

void delete_case4(struct node *n);

void delete_case5(struct node *n);

struct node *LEAF;

struct node *parent(struct node *n) {
return n->parent; // NULL for root node
}

struct node *grandparent(struct node *n) {
struct node *p = parent(n);
if (p == NULL)
return NULL; // No parent means no grandparent
return parent(p); // NULL if parent is root
}

struct node *sibling(struct node *n) {
struct node *p = parent(n);
if (p == NULL)
return NULL; // No parent means no sibling
if (n == p->left)
return p->right;
else
return p->left;
}

struct node *uncle(struct node *n) {
struct node *p = parent(n);
struct node *g = grandparent(n);
if (g == NULL)
return NULL; // No grandparent means no uncle
return sibling(p);
}

void rotate_left(struct node *n) {
struct node *nnew = n->right;
struct node *p = parent(n);
assert(nnew != NULL); // since the leaves of a red-black tree are empty, they cannot become internal nodes
n->right = nnew->left;
nnew->left = n;
n->parent = nnew;
// handle other child/parent pointers
if (n->right != NULL)
n->right->parent = n;
if (p != NULL) // initially n could be the root
{
if (n == p->left)
p->left = nnew;
else if (n == p->right) // if (...) is excessive
p->right = nnew;
}
nnew->parent = p;
}

void rotate_right(struct node *n) {
struct node *nnew = n->left;
struct node *p = parent(n);
assert(nnew != NULL); // since the leaves of a red-black tree are empty, they cannot become internal nodes
n->left = nnew->right;
nnew->right = n;
n->parent = nnew;
// handle other child/parent pointers
if (n->left != NULL)
n->left->parent = n;
if (p != NULL) // initially n could be the root
{
if (n == p->left)
p->left = nnew;
else if (n == p->right) // if (...) is excessive
p->right = nnew;
}
nnew->parent = p;
}

void insert_recurse(struct node *root, struct node *n) {
// recursively descend the tree until a leaf is found
if (root != NULL && n->key < root->key) {
if (root->left != LEAF) {
insert_recurse(root->left, n);
return;
} else
root->left = n;
} else if (root != NULL) {
if (root->right != LEAF) {
insert_recurse(root->right, n);
return;
} else
root->right = n;
}

// insert new node n
n->parent = root;
n->left = LEAF;
n->right = LEAF;
n->color = RED;
}


void insert_case1(struct node *n) {
if (parent(n) == NULL)
n->color = BLACK;
}

void insert_case2(struct node *n) {
return; /* Do nothing since tree is still valid */
}

void insert_case3(struct node *n) {
parent(n)->color = BLACK;
uncle(n)->color = BLACK;
grandparent(n)->color = RED;
insert_repair_tree(grandparent(n));
}

void insert_case4step2(struct node *n) {
struct node *p = parent(n);
struct node *g = grandparent(n);

if (n == p->left)
rotate_right(g);
else
rotate_left(g);
p->color = BLACK;
g->color = RED;
}


void insert_case4(struct node *n) {
struct node *p = parent(n);
struct node *g = grandparent(n);

if (n == g->left->right) {
rotate_left(p);
n = n->left;
} else if (n == g->right->left) {
rotate_right(p);
n = n->right;
}

insert_case4step2(n);
}


void insert_repair_tree(struct node *n) {
if (parent(n) == NULL) {
insert_case1(n);
} else if (parent(n)->color == BLACK) {
insert_case2(n);
} else if (uncle(n)->color == RED) {
insert_case3(n);
} else {
insert_case4(n);
}
}

struct node *insert(struct node *root, struct node *n) {
// insert new node into the current tree
insert_recurse(root, n);

// repair the tree in case any of the red-black properties have been violated
insert_repair_tree(n);

// find the new root to return
root = n;
while (parent(root) != NULL)
root = parent(root);
return root;
}


void replace_node(struct node *n, struct node *child) {
child->parent = n->parent;
if (n == n->parent->left)
n->parent->left = child;
else
n->parent->right = child;
}

int is_leaf(struct node *n) {
if (n->right == NULL && n->left == NULL)
return 1;
else return 0;
}

void delete_one_child(struct node *n) {
/*
* Precondition: n has at most one non-leaf child.
*/
struct node *child = is_leaf(n->right) ? n->left : n->right;

replace_node(n, child);
if (n->color == BLACK) {
if (child->color == RED)
child->color = BLACK;
else
delete_case1(child);
}
free(n);
}

void delete_case1(struct node *n) {
if (n->parent != NULL)
delete_case2(n);
}

void delete_case2(struct node *n) {
struct node *s = sibling(n);

if (s->color == RED) {
n->parent->color = RED;
s->color = BLACK;
if (n == n->parent->left)
rotate_left(n->parent);
else
rotate_right(n->parent);
}
delete_case3(n);
}

void delete_case3(struct node *n) {
struct node *s = sibling(n);

if ((n->parent->color == BLACK) &&
(s->color == BLACK) &&
(s->left->color == BLACK) &&
(s->right->color == BLACK)) {
s->color = RED;
delete_case1(n->parent);
} else
delete_case4(n);
}

void delete_case4(struct node *n) {
struct node *s = sibling(n);

if ((n->parent->color == RED) &&
(s->color == BLACK) &&
(s->left->color == BLACK) &&
(s->right->color == BLACK)) {
s->color = RED;
n->parent->color = BLACK;
} else
delete_case5(n);
}

void delete_case6(struct node *n) {
struct node *s = sibling(n);

s->color = n->parent->color;
n->parent->color = BLACK;

if (n == n->parent->left) {
s->right->color = BLACK;
rotate_left(n->parent);
} else {
s->left->color = BLACK;
rotate_right(n->parent);
}
}

void delete_case5(struct node *n) {
struct node *s = sibling(n);

if (s->color == BLACK) { /* 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 six will rotate correctly. */
if ((n == n->parent->left) &&
(s->right->color == BLACK) &&
(s->left->color == RED)) { /* this last test is trivial too due to cases 2-4. */
s->color = RED;
s->left->color = BLACK;
rotate_right(s);
} else if ((n == n->parent->right) &&
(s->left->color == BLACK) &&
(s->right->color == RED)) {/* this last test is trivial too due to cases 2-4. */
s->color = RED;
s->right->color = BLACK;
rotate_left(s);
}
}
delete_case6(n);
}

struct node *search(struct node *temp, int val) {
int diff;
while (!is_leaf(temp)) {
diff = val - temp->key;
if (diff > 0) {
temp = temp->right;
} else if (diff < 0) {
temp = temp->left;
} else {
printf("Search Element Found!!n");
return temp;
}
}
printf("Given Data Not Found in the tree!!n");
return 0;
}

void inorderTree(struct node *root) {
struct node *temp = root;

if (temp != NULL) {
inorderTree(temp->left);

printf(" %d--%c ", temp->key, temp->color);

inorderTree(temp->right);

}
}

void postorderTree(struct node *root) {
struct node *temp = root;

if (temp != NULL) {
postorderTree(temp->left);
postorderTree(temp->right);
printf(" %d--%c ", temp->key, temp->color);
}
}

void traversal(struct node *root) {
if (root != NULL) {
printf("root is %d-- %c", root->key, root->color);
printf("nInorder tree traversaln");
inorderTree(root);
printf("npostorder tree traversaln");
postorderTree(root);
}
}

int main() {
int T = 1000000000; //test case 1000000000 nodes
int r2;
struct node *root = NULL;
srand(time(NULL));
struct node *z;
LEAF = malloc(sizeof(struct node));
LEAF->color = BLACK;
LEAF->left = NULL;
LEAF->right = NULL;
LEAF->key = 0;
//printf("starting loop!n");
while (T-- > 0) {
r2 = (2 + T) * (rand() % 100); // data
z = malloc(sizeof(struct node));
//printf(" loop!n");
if (z != NULL) {
//printf(" test!n");
z->key = r2;
z->left = NULL;
z->right = NULL;
z->parent = NULL;
z->color = RED;
//printf(" test2!n");
root = insert(root, z);
//printf(" test3!n");
} else printf("malloc failed at node number %d", T);
}
root = NULL;
return 0;
}

int test() {
printf("Hello!n");
struct node *root = NULL;//malloc(sizeof(struct node));
LEAF = malloc(sizeof(struct node));
LEAF->color = BLACK;
LEAF->left = NULL;
LEAF->right = NULL;
LEAF->key = 0;
int choice, val, var, fl = 0;
while (1) {
setbuf(stdout, 0); // Bugfix for debugging mode on Windows
printf("nEnter your choice :1:Add 2:Delete 3:Find 4:Traverse 5: Test 6:Exitn");
scanf("%d", &choice);
switch (choice) {
case 1:
setbuf(stdout, 0);
printf("Enter the integer you want to add : ");
scanf("%d", &val);
struct node *z = malloc(sizeof(struct node));
z->key = val;
z->left = NULL;
z->right = NULL;
z->parent = NULL;
z->color = RED;
root = insert(root, z);
printf("The root is now %d: ", root->key);

break;
case 2:
printf("Enter the integer you want to delete : ");
scanf("%d", &var);
delete_one_child(search(root, var));
break;
case 3:
printf("Enter search element n");
scanf("%d", &val);
search(root, val);
break;
case 4:
traversal(root);
break;
case 5: // TODO
test();
break;
case 6:
fl = 1;
break;
default:
printf("nInvalid Choicen");
}
if (fl == 1) { break; }
}
return 0;
}


I have also added test code which builds up a large tree, the test completes on Linux but on Windows 10 malloc starts returning NULL after approx. 55 million nodes.



   int test() {
int T = 1000000000; //test case 1000000000 nodes
int r2;
struct node *root = NULL;
srand(time(NULL));
struct node *z;
LEAF = malloc(sizeof(struct node));
LEAF->color = BLACK;
LEAF->left = NULL;
LEAF->right = NULL;
LEAF->key = 0;

while (T-- > 0) {
r2 = (2 + T) * (rand() % 100); // data
z = malloc(sizeof(struct node));

if (z != NULL) {

z->key = r2;
z->left = NULL;
z->right = NULL;
z->parent = NULL;
z->color = RED;

root = insert(root, z);

} else printf("malloc failed at node number %d", T);
}
root = NULL;
return 0;
}









share|improve this question




















  • 1




    I get a crash running the test on the first few iterations through the loop. Always on line 181, though the exact number of iterations varies each time. This line: ` } else if (uncle(n)->color == RED) {`. Building on macOS with llvm 9 set to C11.
    – user1118321
    3 hours ago










  • @user1118321 It's because the LEAF was null, I just updated the code with proper test including declaration of LEAF.
    – Niklas Rosencrantz
    3 hours ago








  • 1




    It still crashes for me. Also, you forgot to #include <time.h>.
    – user1118321
    3 hours ago










  • @user1118321 Thanks for testing! It should work from here (including everything) github.com/montao/rbtree2/blob/master/rbtree.c
    – Niklas Rosencrantz
    3 hours ago










  • @user1118321 I am adding tests with an integration server now (travis-ci) to see what comes out. Thanks a lot for testing and reporting back.
    – Niklas Rosencrantz
    3 hours ago















up vote
7
down vote

favorite












I would like to verify that the code fulfills the specification of a red-black tree or receive suggestions for improvements.



#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <time.h>


static char BLACK = 'b';
static char RED = 'r';

struct node {
int key;
char color;
struct node *left, *right, *parent;
};

void insert_repair_tree(struct node *n);

void delete_case1(struct node *n);

void delete_case2(struct node *n);

void delete_case3(struct node *n);

void delete_case4(struct node *n);

void delete_case5(struct node *n);

struct node *LEAF;

struct node *parent(struct node *n) {
return n->parent; // NULL for root node
}

struct node *grandparent(struct node *n) {
struct node *p = parent(n);
if (p == NULL)
return NULL; // No parent means no grandparent
return parent(p); // NULL if parent is root
}

struct node *sibling(struct node *n) {
struct node *p = parent(n);
if (p == NULL)
return NULL; // No parent means no sibling
if (n == p->left)
return p->right;
else
return p->left;
}

struct node *uncle(struct node *n) {
struct node *p = parent(n);
struct node *g = grandparent(n);
if (g == NULL)
return NULL; // No grandparent means no uncle
return sibling(p);
}

void rotate_left(struct node *n) {
struct node *nnew = n->right;
struct node *p = parent(n);
assert(nnew != NULL); // since the leaves of a red-black tree are empty, they cannot become internal nodes
n->right = nnew->left;
nnew->left = n;
n->parent = nnew;
// handle other child/parent pointers
if (n->right != NULL)
n->right->parent = n;
if (p != NULL) // initially n could be the root
{
if (n == p->left)
p->left = nnew;
else if (n == p->right) // if (...) is excessive
p->right = nnew;
}
nnew->parent = p;
}

void rotate_right(struct node *n) {
struct node *nnew = n->left;
struct node *p = parent(n);
assert(nnew != NULL); // since the leaves of a red-black tree are empty, they cannot become internal nodes
n->left = nnew->right;
nnew->right = n;
n->parent = nnew;
// handle other child/parent pointers
if (n->left != NULL)
n->left->parent = n;
if (p != NULL) // initially n could be the root
{
if (n == p->left)
p->left = nnew;
else if (n == p->right) // if (...) is excessive
p->right = nnew;
}
nnew->parent = p;
}

void insert_recurse(struct node *root, struct node *n) {
// recursively descend the tree until a leaf is found
if (root != NULL && n->key < root->key) {
if (root->left != LEAF) {
insert_recurse(root->left, n);
return;
} else
root->left = n;
} else if (root != NULL) {
if (root->right != LEAF) {
insert_recurse(root->right, n);
return;
} else
root->right = n;
}

// insert new node n
n->parent = root;
n->left = LEAF;
n->right = LEAF;
n->color = RED;
}


void insert_case1(struct node *n) {
if (parent(n) == NULL)
n->color = BLACK;
}

void insert_case2(struct node *n) {
return; /* Do nothing since tree is still valid */
}

void insert_case3(struct node *n) {
parent(n)->color = BLACK;
uncle(n)->color = BLACK;
grandparent(n)->color = RED;
insert_repair_tree(grandparent(n));
}

void insert_case4step2(struct node *n) {
struct node *p = parent(n);
struct node *g = grandparent(n);

if (n == p->left)
rotate_right(g);
else
rotate_left(g);
p->color = BLACK;
g->color = RED;
}


void insert_case4(struct node *n) {
struct node *p = parent(n);
struct node *g = grandparent(n);

if (n == g->left->right) {
rotate_left(p);
n = n->left;
} else if (n == g->right->left) {
rotate_right(p);
n = n->right;
}

insert_case4step2(n);
}


void insert_repair_tree(struct node *n) {
if (parent(n) == NULL) {
insert_case1(n);
} else if (parent(n)->color == BLACK) {
insert_case2(n);
} else if (uncle(n)->color == RED) {
insert_case3(n);
} else {
insert_case4(n);
}
}

struct node *insert(struct node *root, struct node *n) {
// insert new node into the current tree
insert_recurse(root, n);

// repair the tree in case any of the red-black properties have been violated
insert_repair_tree(n);

// find the new root to return
root = n;
while (parent(root) != NULL)
root = parent(root);
return root;
}


void replace_node(struct node *n, struct node *child) {
child->parent = n->parent;
if (n == n->parent->left)
n->parent->left = child;
else
n->parent->right = child;
}

int is_leaf(struct node *n) {
if (n->right == NULL && n->left == NULL)
return 1;
else return 0;
}

void delete_one_child(struct node *n) {
/*
* Precondition: n has at most one non-leaf child.
*/
struct node *child = is_leaf(n->right) ? n->left : n->right;

replace_node(n, child);
if (n->color == BLACK) {
if (child->color == RED)
child->color = BLACK;
else
delete_case1(child);
}
free(n);
}

void delete_case1(struct node *n) {
if (n->parent != NULL)
delete_case2(n);
}

void delete_case2(struct node *n) {
struct node *s = sibling(n);

if (s->color == RED) {
n->parent->color = RED;
s->color = BLACK;
if (n == n->parent->left)
rotate_left(n->parent);
else
rotate_right(n->parent);
}
delete_case3(n);
}

void delete_case3(struct node *n) {
struct node *s = sibling(n);

if ((n->parent->color == BLACK) &&
(s->color == BLACK) &&
(s->left->color == BLACK) &&
(s->right->color == BLACK)) {
s->color = RED;
delete_case1(n->parent);
} else
delete_case4(n);
}

void delete_case4(struct node *n) {
struct node *s = sibling(n);

if ((n->parent->color == RED) &&
(s->color == BLACK) &&
(s->left->color == BLACK) &&
(s->right->color == BLACK)) {
s->color = RED;
n->parent->color = BLACK;
} else
delete_case5(n);
}

void delete_case6(struct node *n) {
struct node *s = sibling(n);

s->color = n->parent->color;
n->parent->color = BLACK;

if (n == n->parent->left) {
s->right->color = BLACK;
rotate_left(n->parent);
} else {
s->left->color = BLACK;
rotate_right(n->parent);
}
}

void delete_case5(struct node *n) {
struct node *s = sibling(n);

if (s->color == BLACK) { /* 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 six will rotate correctly. */
if ((n == n->parent->left) &&
(s->right->color == BLACK) &&
(s->left->color == RED)) { /* this last test is trivial too due to cases 2-4. */
s->color = RED;
s->left->color = BLACK;
rotate_right(s);
} else if ((n == n->parent->right) &&
(s->left->color == BLACK) &&
(s->right->color == RED)) {/* this last test is trivial too due to cases 2-4. */
s->color = RED;
s->right->color = BLACK;
rotate_left(s);
}
}
delete_case6(n);
}

struct node *search(struct node *temp, int val) {
int diff;
while (!is_leaf(temp)) {
diff = val - temp->key;
if (diff > 0) {
temp = temp->right;
} else if (diff < 0) {
temp = temp->left;
} else {
printf("Search Element Found!!n");
return temp;
}
}
printf("Given Data Not Found in the tree!!n");
return 0;
}

void inorderTree(struct node *root) {
struct node *temp = root;

if (temp != NULL) {
inorderTree(temp->left);

printf(" %d--%c ", temp->key, temp->color);

inorderTree(temp->right);

}
}

void postorderTree(struct node *root) {
struct node *temp = root;

if (temp != NULL) {
postorderTree(temp->left);
postorderTree(temp->right);
printf(" %d--%c ", temp->key, temp->color);
}
}

void traversal(struct node *root) {
if (root != NULL) {
printf("root is %d-- %c", root->key, root->color);
printf("nInorder tree traversaln");
inorderTree(root);
printf("npostorder tree traversaln");
postorderTree(root);
}
}

int main() {
int T = 1000000000; //test case 1000000000 nodes
int r2;
struct node *root = NULL;
srand(time(NULL));
struct node *z;
LEAF = malloc(sizeof(struct node));
LEAF->color = BLACK;
LEAF->left = NULL;
LEAF->right = NULL;
LEAF->key = 0;
//printf("starting loop!n");
while (T-- > 0) {
r2 = (2 + T) * (rand() % 100); // data
z = malloc(sizeof(struct node));
//printf(" loop!n");
if (z != NULL) {
//printf(" test!n");
z->key = r2;
z->left = NULL;
z->right = NULL;
z->parent = NULL;
z->color = RED;
//printf(" test2!n");
root = insert(root, z);
//printf(" test3!n");
} else printf("malloc failed at node number %d", T);
}
root = NULL;
return 0;
}

int test() {
printf("Hello!n");
struct node *root = NULL;//malloc(sizeof(struct node));
LEAF = malloc(sizeof(struct node));
LEAF->color = BLACK;
LEAF->left = NULL;
LEAF->right = NULL;
LEAF->key = 0;
int choice, val, var, fl = 0;
while (1) {
setbuf(stdout, 0); // Bugfix for debugging mode on Windows
printf("nEnter your choice :1:Add 2:Delete 3:Find 4:Traverse 5: Test 6:Exitn");
scanf("%d", &choice);
switch (choice) {
case 1:
setbuf(stdout, 0);
printf("Enter the integer you want to add : ");
scanf("%d", &val);
struct node *z = malloc(sizeof(struct node));
z->key = val;
z->left = NULL;
z->right = NULL;
z->parent = NULL;
z->color = RED;
root = insert(root, z);
printf("The root is now %d: ", root->key);

break;
case 2:
printf("Enter the integer you want to delete : ");
scanf("%d", &var);
delete_one_child(search(root, var));
break;
case 3:
printf("Enter search element n");
scanf("%d", &val);
search(root, val);
break;
case 4:
traversal(root);
break;
case 5: // TODO
test();
break;
case 6:
fl = 1;
break;
default:
printf("nInvalid Choicen");
}
if (fl == 1) { break; }
}
return 0;
}


I have also added test code which builds up a large tree, the test completes on Linux but on Windows 10 malloc starts returning NULL after approx. 55 million nodes.



   int test() {
int T = 1000000000; //test case 1000000000 nodes
int r2;
struct node *root = NULL;
srand(time(NULL));
struct node *z;
LEAF = malloc(sizeof(struct node));
LEAF->color = BLACK;
LEAF->left = NULL;
LEAF->right = NULL;
LEAF->key = 0;

while (T-- > 0) {
r2 = (2 + T) * (rand() % 100); // data
z = malloc(sizeof(struct node));

if (z != NULL) {

z->key = r2;
z->left = NULL;
z->right = NULL;
z->parent = NULL;
z->color = RED;

root = insert(root, z);

} else printf("malloc failed at node number %d", T);
}
root = NULL;
return 0;
}









share|improve this question




















  • 1




    I get a crash running the test on the first few iterations through the loop. Always on line 181, though the exact number of iterations varies each time. This line: ` } else if (uncle(n)->color == RED) {`. Building on macOS with llvm 9 set to C11.
    – user1118321
    3 hours ago










  • @user1118321 It's because the LEAF was null, I just updated the code with proper test including declaration of LEAF.
    – Niklas Rosencrantz
    3 hours ago








  • 1




    It still crashes for me. Also, you forgot to #include <time.h>.
    – user1118321
    3 hours ago










  • @user1118321 Thanks for testing! It should work from here (including everything) github.com/montao/rbtree2/blob/master/rbtree.c
    – Niklas Rosencrantz
    3 hours ago










  • @user1118321 I am adding tests with an integration server now (travis-ci) to see what comes out. Thanks a lot for testing and reporting back.
    – Niklas Rosencrantz
    3 hours ago













up vote
7
down vote

favorite









up vote
7
down vote

favorite











I would like to verify that the code fulfills the specification of a red-black tree or receive suggestions for improvements.



#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <time.h>


static char BLACK = 'b';
static char RED = 'r';

struct node {
int key;
char color;
struct node *left, *right, *parent;
};

void insert_repair_tree(struct node *n);

void delete_case1(struct node *n);

void delete_case2(struct node *n);

void delete_case3(struct node *n);

void delete_case4(struct node *n);

void delete_case5(struct node *n);

struct node *LEAF;

struct node *parent(struct node *n) {
return n->parent; // NULL for root node
}

struct node *grandparent(struct node *n) {
struct node *p = parent(n);
if (p == NULL)
return NULL; // No parent means no grandparent
return parent(p); // NULL if parent is root
}

struct node *sibling(struct node *n) {
struct node *p = parent(n);
if (p == NULL)
return NULL; // No parent means no sibling
if (n == p->left)
return p->right;
else
return p->left;
}

struct node *uncle(struct node *n) {
struct node *p = parent(n);
struct node *g = grandparent(n);
if (g == NULL)
return NULL; // No grandparent means no uncle
return sibling(p);
}

void rotate_left(struct node *n) {
struct node *nnew = n->right;
struct node *p = parent(n);
assert(nnew != NULL); // since the leaves of a red-black tree are empty, they cannot become internal nodes
n->right = nnew->left;
nnew->left = n;
n->parent = nnew;
// handle other child/parent pointers
if (n->right != NULL)
n->right->parent = n;
if (p != NULL) // initially n could be the root
{
if (n == p->left)
p->left = nnew;
else if (n == p->right) // if (...) is excessive
p->right = nnew;
}
nnew->parent = p;
}

void rotate_right(struct node *n) {
struct node *nnew = n->left;
struct node *p = parent(n);
assert(nnew != NULL); // since the leaves of a red-black tree are empty, they cannot become internal nodes
n->left = nnew->right;
nnew->right = n;
n->parent = nnew;
// handle other child/parent pointers
if (n->left != NULL)
n->left->parent = n;
if (p != NULL) // initially n could be the root
{
if (n == p->left)
p->left = nnew;
else if (n == p->right) // if (...) is excessive
p->right = nnew;
}
nnew->parent = p;
}

void insert_recurse(struct node *root, struct node *n) {
// recursively descend the tree until a leaf is found
if (root != NULL && n->key < root->key) {
if (root->left != LEAF) {
insert_recurse(root->left, n);
return;
} else
root->left = n;
} else if (root != NULL) {
if (root->right != LEAF) {
insert_recurse(root->right, n);
return;
} else
root->right = n;
}

// insert new node n
n->parent = root;
n->left = LEAF;
n->right = LEAF;
n->color = RED;
}


void insert_case1(struct node *n) {
if (parent(n) == NULL)
n->color = BLACK;
}

void insert_case2(struct node *n) {
return; /* Do nothing since tree is still valid */
}

void insert_case3(struct node *n) {
parent(n)->color = BLACK;
uncle(n)->color = BLACK;
grandparent(n)->color = RED;
insert_repair_tree(grandparent(n));
}

void insert_case4step2(struct node *n) {
struct node *p = parent(n);
struct node *g = grandparent(n);

if (n == p->left)
rotate_right(g);
else
rotate_left(g);
p->color = BLACK;
g->color = RED;
}


void insert_case4(struct node *n) {
struct node *p = parent(n);
struct node *g = grandparent(n);

if (n == g->left->right) {
rotate_left(p);
n = n->left;
} else if (n == g->right->left) {
rotate_right(p);
n = n->right;
}

insert_case4step2(n);
}


void insert_repair_tree(struct node *n) {
if (parent(n) == NULL) {
insert_case1(n);
} else if (parent(n)->color == BLACK) {
insert_case2(n);
} else if (uncle(n)->color == RED) {
insert_case3(n);
} else {
insert_case4(n);
}
}

struct node *insert(struct node *root, struct node *n) {
// insert new node into the current tree
insert_recurse(root, n);

// repair the tree in case any of the red-black properties have been violated
insert_repair_tree(n);

// find the new root to return
root = n;
while (parent(root) != NULL)
root = parent(root);
return root;
}


void replace_node(struct node *n, struct node *child) {
child->parent = n->parent;
if (n == n->parent->left)
n->parent->left = child;
else
n->parent->right = child;
}

int is_leaf(struct node *n) {
if (n->right == NULL && n->left == NULL)
return 1;
else return 0;
}

void delete_one_child(struct node *n) {
/*
* Precondition: n has at most one non-leaf child.
*/
struct node *child = is_leaf(n->right) ? n->left : n->right;

replace_node(n, child);
if (n->color == BLACK) {
if (child->color == RED)
child->color = BLACK;
else
delete_case1(child);
}
free(n);
}

void delete_case1(struct node *n) {
if (n->parent != NULL)
delete_case2(n);
}

void delete_case2(struct node *n) {
struct node *s = sibling(n);

if (s->color == RED) {
n->parent->color = RED;
s->color = BLACK;
if (n == n->parent->left)
rotate_left(n->parent);
else
rotate_right(n->parent);
}
delete_case3(n);
}

void delete_case3(struct node *n) {
struct node *s = sibling(n);

if ((n->parent->color == BLACK) &&
(s->color == BLACK) &&
(s->left->color == BLACK) &&
(s->right->color == BLACK)) {
s->color = RED;
delete_case1(n->parent);
} else
delete_case4(n);
}

void delete_case4(struct node *n) {
struct node *s = sibling(n);

if ((n->parent->color == RED) &&
(s->color == BLACK) &&
(s->left->color == BLACK) &&
(s->right->color == BLACK)) {
s->color = RED;
n->parent->color = BLACK;
} else
delete_case5(n);
}

void delete_case6(struct node *n) {
struct node *s = sibling(n);

s->color = n->parent->color;
n->parent->color = BLACK;

if (n == n->parent->left) {
s->right->color = BLACK;
rotate_left(n->parent);
} else {
s->left->color = BLACK;
rotate_right(n->parent);
}
}

void delete_case5(struct node *n) {
struct node *s = sibling(n);

if (s->color == BLACK) { /* 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 six will rotate correctly. */
if ((n == n->parent->left) &&
(s->right->color == BLACK) &&
(s->left->color == RED)) { /* this last test is trivial too due to cases 2-4. */
s->color = RED;
s->left->color = BLACK;
rotate_right(s);
} else if ((n == n->parent->right) &&
(s->left->color == BLACK) &&
(s->right->color == RED)) {/* this last test is trivial too due to cases 2-4. */
s->color = RED;
s->right->color = BLACK;
rotate_left(s);
}
}
delete_case6(n);
}

struct node *search(struct node *temp, int val) {
int diff;
while (!is_leaf(temp)) {
diff = val - temp->key;
if (diff > 0) {
temp = temp->right;
} else if (diff < 0) {
temp = temp->left;
} else {
printf("Search Element Found!!n");
return temp;
}
}
printf("Given Data Not Found in the tree!!n");
return 0;
}

void inorderTree(struct node *root) {
struct node *temp = root;

if (temp != NULL) {
inorderTree(temp->left);

printf(" %d--%c ", temp->key, temp->color);

inorderTree(temp->right);

}
}

void postorderTree(struct node *root) {
struct node *temp = root;

if (temp != NULL) {
postorderTree(temp->left);
postorderTree(temp->right);
printf(" %d--%c ", temp->key, temp->color);
}
}

void traversal(struct node *root) {
if (root != NULL) {
printf("root is %d-- %c", root->key, root->color);
printf("nInorder tree traversaln");
inorderTree(root);
printf("npostorder tree traversaln");
postorderTree(root);
}
}

int main() {
int T = 1000000000; //test case 1000000000 nodes
int r2;
struct node *root = NULL;
srand(time(NULL));
struct node *z;
LEAF = malloc(sizeof(struct node));
LEAF->color = BLACK;
LEAF->left = NULL;
LEAF->right = NULL;
LEAF->key = 0;
//printf("starting loop!n");
while (T-- > 0) {
r2 = (2 + T) * (rand() % 100); // data
z = malloc(sizeof(struct node));
//printf(" loop!n");
if (z != NULL) {
//printf(" test!n");
z->key = r2;
z->left = NULL;
z->right = NULL;
z->parent = NULL;
z->color = RED;
//printf(" test2!n");
root = insert(root, z);
//printf(" test3!n");
} else printf("malloc failed at node number %d", T);
}
root = NULL;
return 0;
}

int test() {
printf("Hello!n");
struct node *root = NULL;//malloc(sizeof(struct node));
LEAF = malloc(sizeof(struct node));
LEAF->color = BLACK;
LEAF->left = NULL;
LEAF->right = NULL;
LEAF->key = 0;
int choice, val, var, fl = 0;
while (1) {
setbuf(stdout, 0); // Bugfix for debugging mode on Windows
printf("nEnter your choice :1:Add 2:Delete 3:Find 4:Traverse 5: Test 6:Exitn");
scanf("%d", &choice);
switch (choice) {
case 1:
setbuf(stdout, 0);
printf("Enter the integer you want to add : ");
scanf("%d", &val);
struct node *z = malloc(sizeof(struct node));
z->key = val;
z->left = NULL;
z->right = NULL;
z->parent = NULL;
z->color = RED;
root = insert(root, z);
printf("The root is now %d: ", root->key);

break;
case 2:
printf("Enter the integer you want to delete : ");
scanf("%d", &var);
delete_one_child(search(root, var));
break;
case 3:
printf("Enter search element n");
scanf("%d", &val);
search(root, val);
break;
case 4:
traversal(root);
break;
case 5: // TODO
test();
break;
case 6:
fl = 1;
break;
default:
printf("nInvalid Choicen");
}
if (fl == 1) { break; }
}
return 0;
}


I have also added test code which builds up a large tree, the test completes on Linux but on Windows 10 malloc starts returning NULL after approx. 55 million nodes.



   int test() {
int T = 1000000000; //test case 1000000000 nodes
int r2;
struct node *root = NULL;
srand(time(NULL));
struct node *z;
LEAF = malloc(sizeof(struct node));
LEAF->color = BLACK;
LEAF->left = NULL;
LEAF->right = NULL;
LEAF->key = 0;

while (T-- > 0) {
r2 = (2 + T) * (rand() % 100); // data
z = malloc(sizeof(struct node));

if (z != NULL) {

z->key = r2;
z->left = NULL;
z->right = NULL;
z->parent = NULL;
z->color = RED;

root = insert(root, z);

} else printf("malloc failed at node number %d", T);
}
root = NULL;
return 0;
}









share|improve this question















I would like to verify that the code fulfills the specification of a red-black tree or receive suggestions for improvements.



#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <time.h>


static char BLACK = 'b';
static char RED = 'r';

struct node {
int key;
char color;
struct node *left, *right, *parent;
};

void insert_repair_tree(struct node *n);

void delete_case1(struct node *n);

void delete_case2(struct node *n);

void delete_case3(struct node *n);

void delete_case4(struct node *n);

void delete_case5(struct node *n);

struct node *LEAF;

struct node *parent(struct node *n) {
return n->parent; // NULL for root node
}

struct node *grandparent(struct node *n) {
struct node *p = parent(n);
if (p == NULL)
return NULL; // No parent means no grandparent
return parent(p); // NULL if parent is root
}

struct node *sibling(struct node *n) {
struct node *p = parent(n);
if (p == NULL)
return NULL; // No parent means no sibling
if (n == p->left)
return p->right;
else
return p->left;
}

struct node *uncle(struct node *n) {
struct node *p = parent(n);
struct node *g = grandparent(n);
if (g == NULL)
return NULL; // No grandparent means no uncle
return sibling(p);
}

void rotate_left(struct node *n) {
struct node *nnew = n->right;
struct node *p = parent(n);
assert(nnew != NULL); // since the leaves of a red-black tree are empty, they cannot become internal nodes
n->right = nnew->left;
nnew->left = n;
n->parent = nnew;
// handle other child/parent pointers
if (n->right != NULL)
n->right->parent = n;
if (p != NULL) // initially n could be the root
{
if (n == p->left)
p->left = nnew;
else if (n == p->right) // if (...) is excessive
p->right = nnew;
}
nnew->parent = p;
}

void rotate_right(struct node *n) {
struct node *nnew = n->left;
struct node *p = parent(n);
assert(nnew != NULL); // since the leaves of a red-black tree are empty, they cannot become internal nodes
n->left = nnew->right;
nnew->right = n;
n->parent = nnew;
// handle other child/parent pointers
if (n->left != NULL)
n->left->parent = n;
if (p != NULL) // initially n could be the root
{
if (n == p->left)
p->left = nnew;
else if (n == p->right) // if (...) is excessive
p->right = nnew;
}
nnew->parent = p;
}

void insert_recurse(struct node *root, struct node *n) {
// recursively descend the tree until a leaf is found
if (root != NULL && n->key < root->key) {
if (root->left != LEAF) {
insert_recurse(root->left, n);
return;
} else
root->left = n;
} else if (root != NULL) {
if (root->right != LEAF) {
insert_recurse(root->right, n);
return;
} else
root->right = n;
}

// insert new node n
n->parent = root;
n->left = LEAF;
n->right = LEAF;
n->color = RED;
}


void insert_case1(struct node *n) {
if (parent(n) == NULL)
n->color = BLACK;
}

void insert_case2(struct node *n) {
return; /* Do nothing since tree is still valid */
}

void insert_case3(struct node *n) {
parent(n)->color = BLACK;
uncle(n)->color = BLACK;
grandparent(n)->color = RED;
insert_repair_tree(grandparent(n));
}

void insert_case4step2(struct node *n) {
struct node *p = parent(n);
struct node *g = grandparent(n);

if (n == p->left)
rotate_right(g);
else
rotate_left(g);
p->color = BLACK;
g->color = RED;
}


void insert_case4(struct node *n) {
struct node *p = parent(n);
struct node *g = grandparent(n);

if (n == g->left->right) {
rotate_left(p);
n = n->left;
} else if (n == g->right->left) {
rotate_right(p);
n = n->right;
}

insert_case4step2(n);
}


void insert_repair_tree(struct node *n) {
if (parent(n) == NULL) {
insert_case1(n);
} else if (parent(n)->color == BLACK) {
insert_case2(n);
} else if (uncle(n)->color == RED) {
insert_case3(n);
} else {
insert_case4(n);
}
}

struct node *insert(struct node *root, struct node *n) {
// insert new node into the current tree
insert_recurse(root, n);

// repair the tree in case any of the red-black properties have been violated
insert_repair_tree(n);

// find the new root to return
root = n;
while (parent(root) != NULL)
root = parent(root);
return root;
}


void replace_node(struct node *n, struct node *child) {
child->parent = n->parent;
if (n == n->parent->left)
n->parent->left = child;
else
n->parent->right = child;
}

int is_leaf(struct node *n) {
if (n->right == NULL && n->left == NULL)
return 1;
else return 0;
}

void delete_one_child(struct node *n) {
/*
* Precondition: n has at most one non-leaf child.
*/
struct node *child = is_leaf(n->right) ? n->left : n->right;

replace_node(n, child);
if (n->color == BLACK) {
if (child->color == RED)
child->color = BLACK;
else
delete_case1(child);
}
free(n);
}

void delete_case1(struct node *n) {
if (n->parent != NULL)
delete_case2(n);
}

void delete_case2(struct node *n) {
struct node *s = sibling(n);

if (s->color == RED) {
n->parent->color = RED;
s->color = BLACK;
if (n == n->parent->left)
rotate_left(n->parent);
else
rotate_right(n->parent);
}
delete_case3(n);
}

void delete_case3(struct node *n) {
struct node *s = sibling(n);

if ((n->parent->color == BLACK) &&
(s->color == BLACK) &&
(s->left->color == BLACK) &&
(s->right->color == BLACK)) {
s->color = RED;
delete_case1(n->parent);
} else
delete_case4(n);
}

void delete_case4(struct node *n) {
struct node *s = sibling(n);

if ((n->parent->color == RED) &&
(s->color == BLACK) &&
(s->left->color == BLACK) &&
(s->right->color == BLACK)) {
s->color = RED;
n->parent->color = BLACK;
} else
delete_case5(n);
}

void delete_case6(struct node *n) {
struct node *s = sibling(n);

s->color = n->parent->color;
n->parent->color = BLACK;

if (n == n->parent->left) {
s->right->color = BLACK;
rotate_left(n->parent);
} else {
s->left->color = BLACK;
rotate_right(n->parent);
}
}

void delete_case5(struct node *n) {
struct node *s = sibling(n);

if (s->color == BLACK) { /* 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 six will rotate correctly. */
if ((n == n->parent->left) &&
(s->right->color == BLACK) &&
(s->left->color == RED)) { /* this last test is trivial too due to cases 2-4. */
s->color = RED;
s->left->color = BLACK;
rotate_right(s);
} else if ((n == n->parent->right) &&
(s->left->color == BLACK) &&
(s->right->color == RED)) {/* this last test is trivial too due to cases 2-4. */
s->color = RED;
s->right->color = BLACK;
rotate_left(s);
}
}
delete_case6(n);
}

struct node *search(struct node *temp, int val) {
int diff;
while (!is_leaf(temp)) {
diff = val - temp->key;
if (diff > 0) {
temp = temp->right;
} else if (diff < 0) {
temp = temp->left;
} else {
printf("Search Element Found!!n");
return temp;
}
}
printf("Given Data Not Found in the tree!!n");
return 0;
}

void inorderTree(struct node *root) {
struct node *temp = root;

if (temp != NULL) {
inorderTree(temp->left);

printf(" %d--%c ", temp->key, temp->color);

inorderTree(temp->right);

}
}

void postorderTree(struct node *root) {
struct node *temp = root;

if (temp != NULL) {
postorderTree(temp->left);
postorderTree(temp->right);
printf(" %d--%c ", temp->key, temp->color);
}
}

void traversal(struct node *root) {
if (root != NULL) {
printf("root is %d-- %c", root->key, root->color);
printf("nInorder tree traversaln");
inorderTree(root);
printf("npostorder tree traversaln");
postorderTree(root);
}
}

int main() {
int T = 1000000000; //test case 1000000000 nodes
int r2;
struct node *root = NULL;
srand(time(NULL));
struct node *z;
LEAF = malloc(sizeof(struct node));
LEAF->color = BLACK;
LEAF->left = NULL;
LEAF->right = NULL;
LEAF->key = 0;
//printf("starting loop!n");
while (T-- > 0) {
r2 = (2 + T) * (rand() % 100); // data
z = malloc(sizeof(struct node));
//printf(" loop!n");
if (z != NULL) {
//printf(" test!n");
z->key = r2;
z->left = NULL;
z->right = NULL;
z->parent = NULL;
z->color = RED;
//printf(" test2!n");
root = insert(root, z);
//printf(" test3!n");
} else printf("malloc failed at node number %d", T);
}
root = NULL;
return 0;
}

int test() {
printf("Hello!n");
struct node *root = NULL;//malloc(sizeof(struct node));
LEAF = malloc(sizeof(struct node));
LEAF->color = BLACK;
LEAF->left = NULL;
LEAF->right = NULL;
LEAF->key = 0;
int choice, val, var, fl = 0;
while (1) {
setbuf(stdout, 0); // Bugfix for debugging mode on Windows
printf("nEnter your choice :1:Add 2:Delete 3:Find 4:Traverse 5: Test 6:Exitn");
scanf("%d", &choice);
switch (choice) {
case 1:
setbuf(stdout, 0);
printf("Enter the integer you want to add : ");
scanf("%d", &val);
struct node *z = malloc(sizeof(struct node));
z->key = val;
z->left = NULL;
z->right = NULL;
z->parent = NULL;
z->color = RED;
root = insert(root, z);
printf("The root is now %d: ", root->key);

break;
case 2:
printf("Enter the integer you want to delete : ");
scanf("%d", &var);
delete_one_child(search(root, var));
break;
case 3:
printf("Enter search element n");
scanf("%d", &val);
search(root, val);
break;
case 4:
traversal(root);
break;
case 5: // TODO
test();
break;
case 6:
fl = 1;
break;
default:
printf("nInvalid Choicen");
}
if (fl == 1) { break; }
}
return 0;
}


I have also added test code which builds up a large tree, the test completes on Linux but on Windows 10 malloc starts returning NULL after approx. 55 million nodes.



   int test() {
int T = 1000000000; //test case 1000000000 nodes
int r2;
struct node *root = NULL;
srand(time(NULL));
struct node *z;
LEAF = malloc(sizeof(struct node));
LEAF->color = BLACK;
LEAF->left = NULL;
LEAF->right = NULL;
LEAF->key = 0;

while (T-- > 0) {
r2 = (2 + T) * (rand() % 100); // data
z = malloc(sizeof(struct node));

if (z != NULL) {

z->key = r2;
z->left = NULL;
z->right = NULL;
z->parent = NULL;
z->color = RED;

root = insert(root, z);

} else printf("malloc failed at node number %d", T);
}
root = NULL;
return 0;
}






algorithm c tree integration-testing






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 3 hours ago

























asked yesterday









Niklas Rosencrantz

641825




641825








  • 1




    I get a crash running the test on the first few iterations through the loop. Always on line 181, though the exact number of iterations varies each time. This line: ` } else if (uncle(n)->color == RED) {`. Building on macOS with llvm 9 set to C11.
    – user1118321
    3 hours ago










  • @user1118321 It's because the LEAF was null, I just updated the code with proper test including declaration of LEAF.
    – Niklas Rosencrantz
    3 hours ago








  • 1




    It still crashes for me. Also, you forgot to #include <time.h>.
    – user1118321
    3 hours ago










  • @user1118321 Thanks for testing! It should work from here (including everything) github.com/montao/rbtree2/blob/master/rbtree.c
    – Niklas Rosencrantz
    3 hours ago










  • @user1118321 I am adding tests with an integration server now (travis-ci) to see what comes out. Thanks a lot for testing and reporting back.
    – Niklas Rosencrantz
    3 hours ago














  • 1




    I get a crash running the test on the first few iterations through the loop. Always on line 181, though the exact number of iterations varies each time. This line: ` } else if (uncle(n)->color == RED) {`. Building on macOS with llvm 9 set to C11.
    – user1118321
    3 hours ago










  • @user1118321 It's because the LEAF was null, I just updated the code with proper test including declaration of LEAF.
    – Niklas Rosencrantz
    3 hours ago








  • 1




    It still crashes for me. Also, you forgot to #include <time.h>.
    – user1118321
    3 hours ago










  • @user1118321 Thanks for testing! It should work from here (including everything) github.com/montao/rbtree2/blob/master/rbtree.c
    – Niklas Rosencrantz
    3 hours ago










  • @user1118321 I am adding tests with an integration server now (travis-ci) to see what comes out. Thanks a lot for testing and reporting back.
    – Niklas Rosencrantz
    3 hours ago








1




1




I get a crash running the test on the first few iterations through the loop. Always on line 181, though the exact number of iterations varies each time. This line: ` } else if (uncle(n)->color == RED) {`. Building on macOS with llvm 9 set to C11.
– user1118321
3 hours ago




I get a crash running the test on the first few iterations through the loop. Always on line 181, though the exact number of iterations varies each time. This line: ` } else if (uncle(n)->color == RED) {`. Building on macOS with llvm 9 set to C11.
– user1118321
3 hours ago












@user1118321 It's because the LEAF was null, I just updated the code with proper test including declaration of LEAF.
– Niklas Rosencrantz
3 hours ago






@user1118321 It's because the LEAF was null, I just updated the code with proper test including declaration of LEAF.
– Niklas Rosencrantz
3 hours ago






1




1




It still crashes for me. Also, you forgot to #include <time.h>.
– user1118321
3 hours ago




It still crashes for me. Also, you forgot to #include <time.h>.
– user1118321
3 hours ago












@user1118321 Thanks for testing! It should work from here (including everything) github.com/montao/rbtree2/blob/master/rbtree.c
– Niklas Rosencrantz
3 hours ago




@user1118321 Thanks for testing! It should work from here (including everything) github.com/montao/rbtree2/blob/master/rbtree.c
– Niklas Rosencrantz
3 hours ago












@user1118321 I am adding tests with an integration server now (travis-ci) to see what comes out. Thanks a lot for testing and reporting back.
– Niklas Rosencrantz
3 hours ago




@user1118321 I am adding tests with an integration server now (travis-ci) to see what comes out. Thanks a lot for testing and reporting back.
– Niklas Rosencrantz
3 hours ago










1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










Some suggestions:




  • Your code is non-reentrant; that is, it can't be called by more than one user at a time due to the global LEAF. Don't have that as a global. It should be passed into your functions, either as a member of a struct if appropriate, or a separate argument.

  • Use typedef so that you don't have to write struct node 100 times.

  • Use const where appropriate. If you're not modifying an argument, e.g. in functions like parent, make the arg const.


  • if (p != NULL) can be written if (p). if (p == NULL) can be written if (!p).

  • Resist the 1980s temptation to declare all of your variables at the top. Declare them where they're used, especially for cases like this -


Your loop



int T = 1000000000; 
....
while (T-- > 0) {


can be written as



for (int T = 1000000000; T > 0; T--)



  • It's good to have tests. It's better to have automated tests. Think about replacing your "interactive" test function with a series of tests that try out various features in your code and apply asserts.






share|improve this answer

















  • 1




    Thanks! I'm making these changes now. The automated test appears: travis-ci.org/montao/rbtree2
    – Niklas Rosencrantz
    3 hours ago













Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207774%2fred-black-tree-in-c%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










Some suggestions:




  • Your code is non-reentrant; that is, it can't be called by more than one user at a time due to the global LEAF. Don't have that as a global. It should be passed into your functions, either as a member of a struct if appropriate, or a separate argument.

  • Use typedef so that you don't have to write struct node 100 times.

  • Use const where appropriate. If you're not modifying an argument, e.g. in functions like parent, make the arg const.


  • if (p != NULL) can be written if (p). if (p == NULL) can be written if (!p).

  • Resist the 1980s temptation to declare all of your variables at the top. Declare them where they're used, especially for cases like this -


Your loop



int T = 1000000000; 
....
while (T-- > 0) {


can be written as



for (int T = 1000000000; T > 0; T--)



  • It's good to have tests. It's better to have automated tests. Think about replacing your "interactive" test function with a series of tests that try out various features in your code and apply asserts.






share|improve this answer

















  • 1




    Thanks! I'm making these changes now. The automated test appears: travis-ci.org/montao/rbtree2
    – Niklas Rosencrantz
    3 hours ago

















up vote
1
down vote



accepted










Some suggestions:




  • Your code is non-reentrant; that is, it can't be called by more than one user at a time due to the global LEAF. Don't have that as a global. It should be passed into your functions, either as a member of a struct if appropriate, or a separate argument.

  • Use typedef so that you don't have to write struct node 100 times.

  • Use const where appropriate. If you're not modifying an argument, e.g. in functions like parent, make the arg const.


  • if (p != NULL) can be written if (p). if (p == NULL) can be written if (!p).

  • Resist the 1980s temptation to declare all of your variables at the top. Declare them where they're used, especially for cases like this -


Your loop



int T = 1000000000; 
....
while (T-- > 0) {


can be written as



for (int T = 1000000000; T > 0; T--)



  • It's good to have tests. It's better to have automated tests. Think about replacing your "interactive" test function with a series of tests that try out various features in your code and apply asserts.






share|improve this answer

















  • 1




    Thanks! I'm making these changes now. The automated test appears: travis-ci.org/montao/rbtree2
    – Niklas Rosencrantz
    3 hours ago















up vote
1
down vote



accepted







up vote
1
down vote



accepted






Some suggestions:




  • Your code is non-reentrant; that is, it can't be called by more than one user at a time due to the global LEAF. Don't have that as a global. It should be passed into your functions, either as a member of a struct if appropriate, or a separate argument.

  • Use typedef so that you don't have to write struct node 100 times.

  • Use const where appropriate. If you're not modifying an argument, e.g. in functions like parent, make the arg const.


  • if (p != NULL) can be written if (p). if (p == NULL) can be written if (!p).

  • Resist the 1980s temptation to declare all of your variables at the top. Declare them where they're used, especially for cases like this -


Your loop



int T = 1000000000; 
....
while (T-- > 0) {


can be written as



for (int T = 1000000000; T > 0; T--)



  • It's good to have tests. It's better to have automated tests. Think about replacing your "interactive" test function with a series of tests that try out various features in your code and apply asserts.






share|improve this answer












Some suggestions:




  • Your code is non-reentrant; that is, it can't be called by more than one user at a time due to the global LEAF. Don't have that as a global. It should be passed into your functions, either as a member of a struct if appropriate, or a separate argument.

  • Use typedef so that you don't have to write struct node 100 times.

  • Use const where appropriate. If you're not modifying an argument, e.g. in functions like parent, make the arg const.


  • if (p != NULL) can be written if (p). if (p == NULL) can be written if (!p).

  • Resist the 1980s temptation to declare all of your variables at the top. Declare them where they're used, especially for cases like this -


Your loop



int T = 1000000000; 
....
while (T-- > 0) {


can be written as



for (int T = 1000000000; T > 0; T--)



  • It's good to have tests. It's better to have automated tests. Think about replacing your "interactive" test function with a series of tests that try out various features in your code and apply asserts.







share|improve this answer












share|improve this answer



share|improve this answer










answered 3 hours ago









Reinderien

932415




932415








  • 1




    Thanks! I'm making these changes now. The automated test appears: travis-ci.org/montao/rbtree2
    – Niklas Rosencrantz
    3 hours ago
















  • 1




    Thanks! I'm making these changes now. The automated test appears: travis-ci.org/montao/rbtree2
    – Niklas Rosencrantz
    3 hours ago










1




1




Thanks! I'm making these changes now. The automated test appears: travis-ci.org/montao/rbtree2
– Niklas Rosencrantz
3 hours ago






Thanks! I'm making these changes now. The automated test appears: travis-ci.org/montao/rbtree2
– Niklas Rosencrantz
3 hours ago




















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207774%2fred-black-tree-in-c%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Costa Masnaga

Fotorealismo

Sidney Franklin