diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..49e9d18 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +assemble: clean + gcc -fPIC -c map_lib.c -o map_lib.o + gcc -shared map_lib.o -o libmap_lib.so + gcc main.c -L. -lmap_lib -o map_test + rm -f ./*.o +clean: + rm -f ./*.o diff --git a/main.c b/main.c new file mode 100644 index 0000000..878baff --- /dev/null +++ b/main.c @@ -0,0 +1,18 @@ +#include +#include +#include "map_lib.h" + +int main() { + Map* my_map = map_create(); + + int value1 = 100; + int value2 = 200; + map_insert(my_map, 10, &value1); + map_insert(my_map, 20, &value2); + int* found = (int*)map_get(my_map, 10); + if (found) printf("Key 10: %d\n", *found); + + map_erase(my_map, 10); + map_destroy(my_map); + return 0; +} \ No newline at end of file diff --git a/map_lib.c b/map_lib.c new file mode 100644 index 0000000..e4c4363 --- /dev/null +++ b/map_lib.c @@ -0,0 +1,253 @@ +#include +#include +#include "map_lib.h" + +Node* createNIL() { + Node* nil = (Node*)malloc(sizeof(Node)); + nil->color = BLACK; + nil->left = nil->right = nil->parent = nil; + return nil; +} + +Map* map_create() { + Map* map = (Map*)malloc(sizeof(Map)); + map->nil = createNIL(); + map->root = map->nil; + return map; +} + +void destroyTree(Node* node, Node* nil) { + if (node == nil) return; + destroyTree(node->left, nil); + destroyTree(node->right, nil); + free(node); +} + +void map_destroy(Map* map) { + destroyTree(map->root, map->nil); + free(map->nil); + free(map); +} + +void left_rotate(Map* map, Node* x) { + Node* y = x->right; + x->right = y->left; + if (y->left != map->nil) + y->left->parent = x; + y->parent = x->parent; + if (x->parent == map->nil) + map->root = y; + else if (x == x->parent->left) + x->parent->left = y; + else + x->parent->right = y; + y->left = x; + x->parent = y; +} + +void right_rotate(Map* map, Node* y) { + Node* x = y->left; + y->left = x->right; + if (x->right != map->nil) + x->right->parent = y; + x->parent = y->parent; + if (y->parent == map->nil) + map->root = x; + else if (y == y->parent->left) + y->parent->left = x; + else + y->parent->right = x; + x->right = y; + y->parent = x; +} + +void insert_fixup(Map* map, Node* z) { + while (z->parent->color == RED) { + if (z->parent == z->parent->parent->left) { + Node* y = z->parent->parent->right; + if (y->color == RED) { + z->parent->color = BLACK; + y->color = BLACK; + z->parent->parent->color = RED; + z = z->parent->parent; + } else { + if (z == z->parent->right) { + z = z->parent; + left_rotate(map, z); + } + z->parent->color = BLACK; + z->parent->parent->color = RED; + right_rotate(map, z->parent->parent); + } + } else { + Node* y = z->parent->parent->left; + if (y->color == RED) { + z->parent->color = BLACK; + y->color = BLACK; + z->parent->parent->color = RED; + z = z->parent->parent; + } else { + if (z == z->parent->left) { + z = z->parent; + right_rotate(map, z); + } + z->parent->color = BLACK; + z->parent->parent->color = RED; + left_rotate(map, z->parent->parent); + } + } + } + map->root->color = BLACK; +} + +void map_insert(Map* map, int key, void* value) { + Node* z = (Node*)malloc(sizeof(Node)); + z->key = key; + z->value = value; + z->color = RED; + z->parent = z->left = z->right = map->nil; + + Node* y = map->nil; + Node* x = map->root; + + while (x != map->nil) { + y = x; + if (z->key < x->key) + x = x->left; + else + x = x->right; + } + + z->parent = y; + if (y == map->nil) + map->root = z; + else if (z->key < y->key) + y->left = z; + else + y->right = z; + + insert_fixup(map, z); +} + +Node* map_find_node(Map* map, int key) { + Node* x = map->root; + while (x != map->nil) { + if (key < x->key) + x = x->left; + else if (x->key < key) + x = x->right; + else + return x; + } + return map->nil; +} + +void* map_get(Map* map, int key) { + Node* node = map_find_node(map, key); + return (node != map->nil) ? node->value : NULL; +} + +Node* minimum(Node* node, Node* nil) { + while (node->left != nil) + node = node->left; + return node; +} + + +void transplant(Map* map, Node* u, Node* v) { + if (u->parent == map->nil) + map->root = v; + else if (u == u->parent->left) + u->parent->left = v; + else + u->parent->right = v; + v->parent = u->parent; +} + +void delete_fixup(Map* map, Node* x) { + while (x != map->root && x->color == BLACK) { + if (x == x->parent->left) { + Node* w = x->parent->right; + if (w->color == RED) { + w->color = BLACK; + x->parent->color = RED; + left_rotate(map, x->parent); + w = x->parent->right; + } + if (w->left->color == BLACK && w->right->color == BLACK) { + w->color = RED; + x = x->parent; + } else { + if (w->right->color == BLACK) { + w->left->color = BLACK; + w->color = RED; + right_rotate(map, w); + w = x->parent->right; + } + w->color = x->parent->color; + x->parent->color = BLACK; + w->right->color = BLACK; + left_rotate(map, x->parent); + x = map->root; + } + } else { + Node* w = x->parent->left; + if (w->color == RED) { + w->color = BLACK; + x->parent->color = RED; + right_rotate(map, x->parent); + w = x->parent->left; + } + if (w->right->color == BLACK && w->left->color == BLACK) { + w->color = RED; + x = x->parent; + } else { + if (w->left->color == BLACK) { + w->right->color = BLACK; + w->color = RED; + left_rotate(map, w); + w = x->parent->left; + } + w->color = x->parent->color; + x->parent->color = BLACK; + w->left->color = BLACK; + right_rotate(map, x->parent); + x = map->root; + } + } + } + x->color = BLACK; +} + +void map_erase(Map* map, int key) { + Node* z = map_find_node(map, key); + if (z == map->nil) return; + + Node* y = z; + Node* x; + Color y_original_color = y->color; + + if (z->left == map->nil) { + x = z->right; + transplant(map, z, z->right); + } else if (z->right == map->nil) { + x = z->left; + transplant(map, z, z->left); + } else { + y = minimum(z->right, map->nil); + y_original_color = y->color; + x = y->right; + transplant(map, y, x); + y->right = z->right; + y->right->parent = y; + transplant(map, z, y); + y->left = z->left; + y->left->parent = y; + y->color = z->color; + } + + if (y_original_color == BLACK) + delete_fixup(map, x); + + free(z); +} diff --git a/map_lib.h b/map_lib.h new file mode 100644 index 0000000..dd11397 --- /dev/null +++ b/map_lib.h @@ -0,0 +1,30 @@ +#pragma once + +typedef enum { RED, BLACK } Color; + +typedef struct Node { + int key; + void* value; + Color color; + struct Node* parent; + struct Node* left; + struct Node* right; +} Node; + +typedef struct { + Node* root; + Node* nil; +} Map; + +Map* map_create(); + +void map_destroy(Map* map); + +void map_insert(Map* map, int key, void* value); + +Node* map_find_node(Map* map, int key); + +void* map_get(Map* map, int key); + +void map_erase(Map* map, int key); +