dimanche 19 août 2018

Implementing red-black tree in C

I'm trying to implement red-black trees in C. I was studying from the source code on GeeksForGeek and tried implementing it in C (since, originally it was in C++). When I ran the code I wrote, it is generating a tree whose root is always either 2, 4, 8, 16 32 ... (depending on the input, since my input is integer starting from 1 in ascending order). Can someone please point out something that I've been doing wrong?

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

enum Color {
    BLACK, RED
};

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

struct node* NewNode(int key) {

    struct node *temp = (struct node *)malloc(sizeof(struct node));
    if (NULL == temp) {
        return NULL;
    }

    temp->key = key;
    temp->left = temp->right = temp->parent = NULL;
    temp->color = RED;

    return temp;
}

struct node* BSTInsert(struct node **root, struct node **insert) {

    if (NULL == *root) {
        return *insert;
    }
    else {

        if ((*insert)->key < (*root)->key) {
            (*root)->left = BSTInsert(&((*root)->left), insert);
            (*root)->left->parent = *root;
        }
        else if ((*insert)->key > (*root)->key) {
            (*root)->right = BSTInsert(&((*root)->right), insert);
            (*root)->right->parent = *root;
        }

        return *root;
    }
}

void RotateLeft(struct node **root, struct node **insert) {

    struct node *right_node = (*insert)->right;

    (*insert)->right = right_node->left;

    if (NULL != (*insert)->right) {
        (*insert)->right->parent = (*insert);
    }

    right_node->parent = (*insert)->parent;

    if (NULL == (*insert)->parent) {
        *root = right_node;
    }
    else if ((*insert) == (*insert)->parent->left){
        (*insert)->parent->left = right_node;
    }
    else {
        (*insert)->parent->right = right_node;
    }

    right_node->left = *insert;
    (*insert)->parent = right_node;
}

void RotateRight(struct node **root, struct node **insert) {

    struct node *left_node = (*insert)->left;

    (*insert)->left = left_node->right;

    if (NULL != (*insert)->left) {
        (*insert)->left->parent = (*insert);
    }

    left_node->parent = (*insert)->parent;

    if (NULL == (*insert)->parent) {
        *root = left_node;
    }
    else if ((*insert) == (*insert)->parent->left) {
        (*insert)->parent->left = left_node;
    }
    else {
        (*insert)->parent->right = left_node;
    }

    left_node->right = (*insert);
    (*insert)->parent = left_node;
}

void FixViolation(struct node **root, struct node **insert) {

    struct node *parent_node, *grand_node;

    while ((*insert != *root) && (BLACK != (*insert)->color) && (RED == (*insert)->parent->color)) {

        parent_node = (*insert)->parent;
        grand_node = (*insert)->parent->parent;

        if (parent_node == grand_node->left) {

            struct node *uncle_node = grand_node->right;

            if (NULL != uncle_node && RED == uncle_node->color) {

                grand_node->color = RED;
                parent_node->color = uncle_node->color = BLACK;
                *insert = grand_node;
            }
            else {

                if (*insert == parent_node->right) {

                    RotateLeft(root, &parent_node);
                    *insert = parent_node;
                    parent_node = (*insert)->parent;
                }

                RotateRight(root, &grand_node);

                int temp = parent_node->color;
                parent_node->color = grand_node->color;
                grand_node->color = temp;

                *insert = parent_node;
            }
        }
        else {

            struct node *uncle_node = grand_node->left;

            if (NULL != uncle_node && RED == uncle_node->color) {

                grand_node->color = RED;
                parent_node->color = uncle_node->color = BLACK;
                *insert = grand_node;
            }
            else {

                if (*insert == parent_node->left) {

                    RotateRight(root, &parent_node);
                    *insert = parent_node;
                    parent_node = (*insert)->parent;
                }

                RotateLeft(root, &grand_node);
                int temp = parent_node->color;
                parent_node->color = grand_node->color;
                grand_node->color = temp;
                *insert = parent_node;
            }
        }
    }

    (*root)->color = BLACK;
}

void Insert(struct node **root, int key) {

    struct node *insert = NewNode(key);
    if (NULL == insert) {
        printf("Memory cannot be allocated.\n");
        return;
    }

    *root = BSTInsert(root, &insert);
    FixViolation(root, &insert);
}

void Inorder(struct node *root) {

    if (NULL != root) {

        Inorder(root->left);
        printf("%d  ", root->key);
        Inorder(root->right);
    }
}

int main() {

    struct node *root = NULL;

    for (int i = 0; i < 20; i++) {
        Insert(&root, i + 1);
    }

    Inorder(root);
    printf("\nRoot : %d\n", root->key);

    return 0;
}

Aucun commentaire:

Enregistrer un commentaire