Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions BDZ2/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CC=gcc
CFLAGS=-Iinclude -Wall -g
LIB=build/librbmap.so

all: $(LIB)

$(LIB): src/rbmap.c
$(CC) $(CFLAGS) -fPIC -shared -o $(LIB) src/rbmap.c

test: $(LIB)
$(CC) -o build/test tests/test_rbmap.c tests/unity.c -Iinclude -Lbuild -lrbmap
LD_LIBRARY_PATH=build ./build/test

clean:
rm -rf build/*
Binary file added BDZ2/build/librbmap.so
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не надо собранные файлы заливать на гит 👎

Binary file not shown.
Binary file added BDZ2/build/test
Binary file not shown.
23 changes: 23 additions & 0 deletions BDZ2/include/rbmap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef RBMAP_H
#define RBMAP_H

typedef enum { RED, BLACK } Color;

typedef struct RBNode {
void *key;
void *value;
Color color;
struct RBNode *left, *right, *parent;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Определение в ряд лучше не делать. Сделай их отдельными

} RBNode;

typedef struct {
RBNode *root;
int (*cmp)(void *, void *);
} RBMap;

RBMap *rbmap_create(int (*cmp)(const void *, const void *));
void rbmap_insert(RBMap *map, void *key, void *value);
void *rbmap_get(RBMap *map, void *key);
void rbmap_destroy(RBMap *map, void (*free_func)(void *, void *));

#endif // RBMAP_H
129 changes: 129 additions & 0 deletions BDZ2/src/rbmap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#include "rbmap.h"
#include <stdio.h>


static RBNode *create_node(void *key, void *value, Color color) {
RBNode *node = malloc(sizeof(RBNode));
node->key = key;
node->value = value;
node->color = color;
node->left = node->right = node->parent = NULL;
return node;
}

static void left_rotate(RBMap *map, RBNode *x) {
RBNode *y = x->right;
x->right = y->left;
if (y->left) y->left->parent = x;
y->parent = x->parent;
if (!x->parent) map->root = y;
else if (x == x->parent->left) x->parent->left = y;
else x->parent->right = y;
y->left = x;
x->parent = y;
}

static void right_rotate(RBMap *map, RBNode *y) {
RBNode *x = y->left;
y->left = x->right;
if (x->right) x->right->parent = y;
x->parent = y->parent;
if (!y->parent) map->root = x;
else if (y == y->parent->right) y->parent->right = x;
else y->parent->left = x;
x->right = y;
y->parent = x;
}

static void insert_fixup(RBMap *map, RBNode *z) {
while (z->parent && z->parent->color == RED) {
if (z->parent == z->parent->parent->left) {
RBNode *y = z->parent->parent->right;
if (y && 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 {
RBNode *y = z->parent->parent->left;
if (y && 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 rbmap_insert(RBMap *map, void *key, void *value) {
RBNode *z = create_node(key, value, RED);
RBNode *y = NULL;
RBNode *x = map->root;

while (x) {
y = x;
int cmp = map->cmp(key, x->key);
if (cmp == 0) {
x->value = value; // заменить значение
free(z);
return;
}
x = (cmp < 0) ? x->left : x->right;
}

z->parent = y;
if (!y) map->root = z;
else if (map->cmp(key, y->key) < 0) y->left = z;
else y->right = z;

insert_fixup(map, z);
}

void *rbmap_get(RBMap *map, void *key) {
RBNode *current = map->root;
while (current) {
int cmp = map->cmp(key, current->key);
if (cmp == 0) return current->value;
current = (cmp < 0) ? current->left : current->right;
}
return NULL; // ключ не найден
}

static void destroy_node(RBNode *node, void (*free_func)(void *, void *)) {
if (!node) return;
destroy_node(node->left, free_func);
destroy_node(node->right, free_func);
if (free_func) free_func(node->key, node->value);
free(node);
}

void rbmap_destroy(RBMap *map, void (*free_func)(void *, void *)) {
destroy_node(map->root, free_func);
free(map);
}

RBMap *rbmap_create(int (*cmp)(const void *, const void *)) {
RBMap *map = malloc(sizeof(RBMap));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

проверка на null

map->root = NULL;
map->cmp = cmp;
return map;
}
49 changes: 49 additions & 0 deletions BDZ2/tests/test_rbmap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "unity.h"
#include "rbmap.h"
#include <stdlib.h>
#include <string.h>

int int_cmp(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}

void setUp(void) {}
void tearDown(void) {}

void test_create_map(void) {
RBMap *map = rbmap_create(int_cmp);
TEST_ASSERT_NOT_NULL(map);
rbmap_destroy(map, free);
}

void test_insert_and_get(void) {
RBMap *map = rbmap_create(int_cmp);
int *key = malloc(sizeof(int));
int *val = malloc(sizeof(int));
*key = 42;
*val = 100;
rbmap_insert(map, key, val);

int query = 42;
int *found = (int *)rbmap_get(map, &query);
TEST_ASSERT_NOT_NULL(found);
TEST_ASSERT_EQUAL_INT(100, *found);

rbmap_destroy(map, free);
}

void test_not_found(void) {
RBMap *map = rbmap_create(int_cmp);
int key = 123;
void *res = rbmap_get(map, &key);
TEST_ASSERT_NULL(res);
rbmap_destroy(map, free);
}

int main(void) {
UNITY_BEGIN();
RUN_TEST(test_create_map);
RUN_TEST(test_insert_and_get);
RUN_TEST(test_not_found);
return UNITY_END();
}
Loading