diff --git a/collective_coding/hashmap/.gitignore b/collective_coding/hashmap/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..f0c9b8122456fb3f2152d72e36d0628bba71fa97 --- /dev/null +++ b/collective_coding/hashmap/.gitignore @@ -0,0 +1,2 @@ +*.o +main diff --git a/collective_coding/hashmap/Makefile b/collective_coding/hashmap/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c4ed718e466b1ac49256e9e4c7c3a1d630178cb1 --- /dev/null +++ b/collective_coding/hashmap/Makefile @@ -0,0 +1,20 @@ +CC=gcc +CFLAGS=-g -std=gnu11 -Wall -Wextra -pedantic -fsanitize=address -fsanitize=leak -fsanitize=undefined +LDFLAGS=-fsanitize=address -fsanitize=leak -fsanitize=undefined +SOURCES=$(wildcard *.c) +OBJECTS=$(SOURCES:.c=.o) + +TARGET = main + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CC) $^ -o $@ $(LDFLAGS) + +hm.c: hm.h + +.PHONY = clean + +clean: + rm -f $(OBJECTS) $(TARGET) + diff --git a/collective_coding/hashmap/hm.c b/collective_coding/hashmap/hm.c new file mode 100644 index 0000000000000000000000000000000000000000..bfc4f73c4d2eb699a0b8711254cd62bd21d25e0a --- /dev/null +++ b/collective_coding/hashmap/hm.c @@ -0,0 +1,91 @@ +#include "hm.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static int hash(char *key, int capacity) { + int h = 0; + for (size_t i = 0; i < strlen(key); ++i) { + h = (h + key[i] * 43) % capacity; + } + return h; +} + +static int rehash(char *key) { + return 1; +} + +static int find_index(hm h, char *key) { + int i = hash(key, h.capacity); + int init = i; + while (h.table[i].state != empty && + strncmp(h.table[i].key, key, MAX_LEN) != 0) { + i = (i + rehash(key)) % h.capacity; + if (i == init) { + return -1; + } + } + return i; +} + +void hm_init(hm *h, int capacity) { + h->table = malloc(capacity * sizeof(cell_t)); + h->capacity = capacity; + for (int i = 0; i < h->capacity; ++i) { + h->table[i].state = empty; + } +} + +void hm_destroy(hm *h) { + free(h->table); + h->table = NULL; + h->capacity = -1; +} + +bool hm_set(hm *h, char *key, char *value) { + int i = hash(key, h->capacity); + int init = i; + while (h->table[i].state == occupied && + strncmp(h->table[i].key, key, MAX_LEN) != 0) { + i = (i + rehash(key)) % h->capacity; + if (i == init) { + return false; + } + } + if (strncpy(h->table[i].key, key, MAX_LEN) == NULL) { + return false; + }; + if (strncpy(h->table[i].value, value, MAX_LEN) == NULL) { + return false; + }; + h->table[i].state = occupied; + return true; +} + +char *hm_get(hm h, char *key) { + int i = find_index(h, key); + return (i >= 0 && h.table[i].state == occupied) ? h.table[i].value : NULL; +} + +char *hm_remove(hm *h, char *key) { + int i = find_index(*h, key); + if (i >= 0 && h->table[i].state == occupied) { + h->table[i].state = deleted; + return h->table[i].value; + } else { + return NULL; + } +} + +void hm_print(hm h) { + for (int i = 0; i < h.capacity; ++i) { + if (h.table[i].state == occupied) { + printf("[%d], key: %s, value: %s\n", i, h.table[i].key, + h.table[i].value); + + } else { + printf("[%d], key: none, value: none\n", i); + } + } +} + diff --git a/collective_coding/hashmap/hm.h b/collective_coding/hashmap/hm.h new file mode 100644 index 0000000000000000000000000000000000000000..c7d85f83326ceb267301e6d73e7da5dbaa5cfb84 --- /dev/null +++ b/collective_coding/hashmap/hm.h @@ -0,0 +1,28 @@ +#ifndef _HM_H_ +#define _HM_H_ + +#include <stdbool.h> + +#define MAX_LEN 80 + +typedef enum { empty, occupied, deleted } state_t; + +typedef struct _cell_t { + state_t state; + char key[MAX_LEN]; + char value[MAX_LEN]; +} cell_t; + +typedef struct _hm { + int capacity; + cell_t *table; +} hm; + +void hm_init(hm *h, int capacity); +void hm_destroy(hm *h); +bool hm_set(hm *h, char *key, char *value); +char *hm_get(hm h, char *key); +char *hm_remove(hm *h, char *key); +void hm_print(hm h); + +#endif diff --git a/collective_coding/hashmap/main.c b/collective_coding/hashmap/main.c new file mode 100644 index 0000000000000000000000000000000000000000..e92eead169197fa53c4c4206b136d6265c360b5c --- /dev/null +++ b/collective_coding/hashmap/main.c @@ -0,0 +1,48 @@ +#include "hm.h" +#include <stdio.h> + +int main() { + hm h; + hm_init(&h, 5); + for (int i = 0; i < 7; ++i) { + char key[MAX_LEN], value[MAX_LEN]; + printf("Enter key please:\n"); + scanf("%s", key); + printf("Enter value please:\n"); + scanf("%s", value); + hm_set(&h, key, value); + hm_print(h); + } + printf("DELETE VALUES!\n"); + for (int i = 0; i < 2; ++i) { + char key[MAX_LEN]; + printf("Enter key please:\n"); + scanf("%s", key); + printf("Value: "); + char *value = hm_remove(&h, key); + if (value == NULL) { + printf("Key not found.\n"); + } else { + printf("Value is %s.\n", value); + } + hm_print(h); + } + printf("SEARCH VALUES!\n"); + for (int i = 0; i < 2; ++i) { + char key[MAX_LEN]; + printf("Enter key please:\n"); + scanf("%s", key); + printf("Value: "); + char *value = hm_get(h, key); + if (value == NULL) { + printf("Key not found.\n"); + } else { + printf("Value is %s.\n", value); + } + } + hm_destroy(&h); + /* for (int i = 0; i < 6; ++i) { */ + /* scanf("%s", key); */ + /* scanf("%s", value); */ + /* } */ +}