diff --git a/hashmap/Makefile b/hashmap/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5a6bdb5b41008b6d779361ecc7f34bada68469b0 --- /dev/null +++ b/hashmap/Makefile @@ -0,0 +1,24 @@ +cc=gcc +CFLAGS=-Wextra -Wall -g -fsanitize=address -fsanitize=leak +LFLAGS=-fsanitize=address -fsanitize=leak -lm + +# test :test.x +# ./test.x + +# test.x: hash.o test.o munit.o +# $(cc) -o $@ $^ $(CFLAGS) $(LFLAGS) + +# munit.o: munit/munit.c munit/munit.h +# $(CC) $^ -c + +main: main.x + ./main.x + +main.x: hash.o main.o lst_vec.o + $(cc) -o $@ $^ $(CFLAGS) $(LFLAGS) + +# lst_vec.o: ../lst-vector/lst_vec.h ../lst-vector/lst_vec.c +# $(CC) $^ -c + +clean: + rm -f *.o *.x diff --git a/hashmap/hash.c b/hashmap/hash.c new file mode 100644 index 0000000000000000000000000000000000000000..c027c3fa47e75ce14102eaa1e686697df879e1be --- /dev/null +++ b/hashmap/hash.c @@ -0,0 +1,112 @@ +#include "hash.h" +#include "lst_vec.h" +#include <stdlib.h> +#include <string.h> + +// typedef struct _element { +// void *data; +// struct _element *next; +// } element; + +typedef struct _entry_t { + char *key; + char *value; +} entry_t; + +typedef struct _hm_t { + element **elements; + int length; +} hm_t; + +// +int hash(char *str, int length) { + int val = 0; + int len = strlen(str); + for (int i = 0; i < len; ++i) { + val = 43 * val + str[i]; + } + + return (val % length); +} + +// création d'un pointeur vers une hm +hm_t *hm_create(int length) { + hm_t *hm = malloc(sizeof(hm_t)); + hm->length = length; + hm->elements = malloc(sizeof(element *) * length); + for (int i = 0; i < length; ++i) { + hm->elements[i] = lst_vector_init(); // NULL + } + return hm; +} + +// destruction de la hm et libération de la mémoire +void hm_destroy(hm_t **hm) { + for (int i = 0; i < (*hm)->length; ++i) { + int len = lst_vector_length(&(*hm)->elements[i]); + for (int j = 0; j < len; j++) { + + element *el = lst_vector_pop(&(*hm)->elements[i]); + entry_t *tmp = el->data; + free(tmp->key); + free(tmp->value); + free(tmp); + free(el); + } + } + free((*hm)->elements); + free(*hm); + hm = NULL; +} + +entry_t *createEntry(char *key, char *value) { + entry_t *entry = malloc(sizeof(entry_t)); + entry->key = malloc(sizeof(char) * (strlen(key) + 1)); + entry->value = malloc(sizeof(char) * (strlen(key) + 1)); + strcpy(entry->key, key); + strcpy(entry->value, value); + return entry; +} + +bool isSameKey(char *key, void *x) { + return 0 == strcmp(((entry_t *)x)->key, key); +} + +// insère la paire key-value dans la hm. si key est déjà présente écraser value +// dans la hm. + +hm_t *hm_set(hm_t *hm, char *key, char *value) { + int h = hash(key, hm->length); + printf("h(%s) = %d\n", key, h); + element *el = find_element(&hm->elements[h], isSameKey, key); + + if (el != NULL) { // same key -> update val + // printf("update value\n"); + strcpy(((entry_t *)(el->data))->value, value); + } else { // key is unique -> push it + // printf("push\n"); + lst_vector_push(&hm->elements[h], (void *)createEntry(key, value)); + } + + return hm; +} + +// retourne la valeur associé à la clé, key +char *hm_get(hm_t *hm, char *key) { + + element *el = + find_element(&hm->elements[hash(key, hm->length)], isSameKey, key); + if (el == NULL) { + return "NULL"; + } + return ((entry_t *)(el->data))->value; +} + +// retire une clé de la hm et la retourne +char *hm_rm(hm_t *hm, char *key){ + element *el =find_element(&hm->elements[hash(key, hm->length)], isSameKey, key); +} +// convertit la hm en chaîne de caractères +char *hm_to_str(hm_t *hm); +// affiche le contenu de la hm +void hm_print(hm_t *hm); \ No newline at end of file diff --git a/hashmap/hash.h b/hashmap/hash.h new file mode 100644 index 0000000000000000000000000000000000000000..f4f5278045d90db30f366cf2243b381c88262ec6 --- /dev/null +++ b/hashmap/hash.h @@ -0,0 +1,29 @@ +#ifndef _HASH_H_ +#define _HASH_H_ + +#include <malloc.h> +#include <stdbool.h> +#include <stdio.h> + + +typedef struct _entry_t entry_t; + +typedef struct _hm_t hm_t; + +// création d'un pointeur vers une hm +hm_t *hm_create(int length); +// destruction de la hm et libération de la mémoire +void hm_destroy(hm_t **hm); + +// insère la paire key-value dans la hm. si key est déjà présente +// écraser value dans la hm. +hm_t *hm_set(hm_t *hm, char *key, char *value); +// retourne la valeur associé à la clé, key +char *hm_get(hm_t *hm, char *key); +// retire une clé de la hm et la retourne +char *hm_rm(hm_t *hm, char *key); +// convertit la hm en chaîne de caractères +char *hm_to_str(hm_t *hm); +// affiche le contenu de la hm +void hm_print(hm_t *hm); +#endif \ No newline at end of file diff --git a/hashmap/lst_vec.c b/hashmap/lst_vec.c new file mode 100644 index 0000000000000000000000000000000000000000..2c9b1fedfc5c8c337d97a4cc9aaf8646795016ea --- /dev/null +++ b/hashmap/lst_vec.c @@ -0,0 +1,222 @@ +#include "lst_vec.h" +#include "hash.h" +#include <assert.h> +#include <malloc.h> +#include <stdio.h> +#include <stdlib.h> + +// typedef struct _element { +// void *data; +// struct _element *next; +// } element; + +// typedef element* lst_vector; + +void *square(void *a) { + *(int *)a *= *(int *)a; + return a; +} + +bool isEven(void *a) { return *(int *)a % 2 == 0; } + +lst_vector lst_vector_init() { return NULL; } + +element *move(lst_vector *v, int index) { + element *current = *v; + for (int i = 0; i < index; i++) { + // printf("%d\n",i); + assert(current != NULL); + current = current->next; + } + return current; +} + +int lst_vector_length(lst_vector *v) { + + if (v == NULL) { + return -1; + } + + int size = 0; + element *current = *v; + while (current != NULL) { + size++; + current = current->next; + } + return size; +} + +lst_vector lst_vector_push(lst_vector *v, void *data) { + if (v == NULL) { + return NULL; + } + element *tmp = malloc(sizeof(element)); + tmp->data = data; + tmp->next = *v; + *v = tmp; + return tmp; +} + +element *lst_vector_pop(lst_vector *v) { + if (v == NULL) { + return NULL; + } + element *pop = *v; + *v = (*v)->next; + return pop; +} + +lst_vector lst_vector_set(lst_vector *v, int index, void *data) { + + if (v == NULL || index < 0 || index >= lst_vector_length(v)) { + return NULL; + } + element *current = move(v, index); + free(current->data); + current->data = data; + return *v; +} + +element *lst_vector_get(lst_vector *v, int index) { + if (v == NULL || index < 0 || index >= lst_vector_length(v)) { + return NULL; + } + element *current = move(v, index); + return current; +} + +element *lst_vector_remove(lst_vector *v, int index) { + if (v == NULL || index < 0 || index >= lst_vector_length(v)) { + return NULL; + } + element *current = move(v, index - 1); + element *removed = current->next; + current->next = current->next->next; // jump 1 element + return removed; +} + +lst_vector lst_vector_insert(lst_vector *v, void *data, int index) { + + if (v == NULL || index < 0 || index > lst_vector_length(v)) { + return NULL; + } + + if (index == 0) { + lst_vector_push(v, data); + } else { + element *current = move(v, index - 1); + lst_vector_push(¤t->next, data); + } + return *v; +} + +void lst_vector_empty(lst_vector *v) { + + if (v == NULL) { + return; + } + element *delete; + + while ((*v)->next != NULL) { + delete = *v; + *v = (*v)->next; + free(delete); + } + free(*v); +} + +lst_vector lst_vector_map(lst_vector *v, void *(*f)(void *)) { + + if (v == NULL) { + return NULL; + } + + int index = 0; + element *current = *v; + lst_vector new_vec = lst_vector_init(); + + while (current != NULL) { + lst_vector_insert(&new_vec, f(current->data), index); + current = current->next; + index++; + } + return new_vec; +} + +lst_vector lst_vector_filter(lst_vector *v, bool (*f)(void *)) { + + if (v == NULL) { + return NULL; + } + + int index = 0; + element *current = *v; + lst_vector new_vec = lst_vector_init(); + + while (current != NULL) { + + if (f(current->data)) { + lst_vector_insert(&new_vec, current->data, index); + index++; + } + current = current->next; + } + return new_vec; +} + +element *find_element(lst_vector *v, bool (*f)(char *, void *), char *key) { + if (v == NULL) { + return NULL; + } + element *current = *v; + while (current != NULL) { + + if (f(key, current->data)) { + return current; + } + current = current->next; + } + return NULL; +} + +void vec_print(lst_vector v) { + while (v != NULL) { + printf("%d\n", *(int *)(v->data)); + v = v->next; + } + printf("\n"); +} + +void clearLoop(lst_vector v) { + while (v != NULL) { + free(v->data); + v = v->next; + } +} + +// int main() { + +// lst_vector vec = lst_vector_init(); +// for (int i = 0; i < 5; i++) { +// int *x = malloc(sizeof(int)); +// *x = i; + +// assert(lst_vector_insert(&vec, x, i)!=NULL); +// //lst_vector_push(&vec, x); //same but contrary way ! +// } +// printf("size: %d\n\n",lst_vector_length(&vec)); +// vec_print(vec); +// lst_vector v2=lst_vector_map(&vec,square); +// assert(v2!=NULL); +// lst_vector v3=lst_vector_filter(&vec, isEven); +// assert(v3!=NULL); +// vec_print(v2); +// vec_print(v3); + +// clearLoop(vec); +// lst_vector_empty(&vec); +// lst_vector_empty(&v2); +// lst_vector_empty(&v3); + +// return EXIT_SUCCESS; +// } \ No newline at end of file diff --git a/hashmap/lst_vec.h b/hashmap/lst_vec.h new file mode 100644 index 0000000000000000000000000000000000000000..1285c66f0e10fba3bc5e505603fc80e1792cf791 --- /dev/null +++ b/hashmap/lst_vec.h @@ -0,0 +1,38 @@ +#ifndef _LST_VEC_H_ +#define _LST_VEC_H_ + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <assert.h> +#include "hash.h" + + +typedef struct _element { + void *data; + struct _element *next; +} element; + +typedef element* lst_vector; + +void vec_print(lst_vector v); +lst_vector lst_vector_init(); +int lst_vector_length(lst_vector *v); +lst_vector lst_vector_push(lst_vector *v, void *data); +element *lst_vector_pop(lst_vector *v); +lst_vector lst_vector_set(lst_vector *v, int index, void *data); +element *lst_vector_get(lst_vector *v, int index); +element *lst_vector_remove(lst_vector *v, int index); +lst_vector lst_vector_insert(lst_vector *v, void *data, int index); +void lst_vector_empty(lst_vector *v); + + +element *find_element(lst_vector *v, bool (*f)(char*,void *),char* key); +lst_vector lst_vector_map(lst_vector *v, void *(*f)(void *)); +lst_vector lst_vector_filter(lst_vector *v, bool (*f)(void *)); + + + +#endif + diff --git a/hashmap/main.c b/hashmap/main.c new file mode 100644 index 0000000000000000000000000000000000000000..3fe0928da600fa6efc955ca3b69b1595d6bec6e7 --- /dev/null +++ b/hashmap/main.c @@ -0,0 +1,26 @@ +#include "hash.h" + +int main() { + + hm_t *hm = hm_create(10); + + hm_set(hm, "key1", "1"); + hm_set(hm, "key1", "1"); + hm_set(hm, "key2", "2"); + hm_set(hm, "key3", "3"); + printf("%s\n", hm_get(hm, "key3")); + + hm_destroy(&hm); + + // insère la paire key-value dans la hm. si key est déjà présente + // // écraser value dans la hm. + // hm_t *hm_set(hm_t *hm, const char *const key, const char *const value); + // // retourne la valeur associé à la clé, key + // char *hm_get(const hm_t *const hm, const char *const key); + // // retire une clé de la hm et la retourne + // char *hm_rm(hm_t *hm, const char *const key); + // // convertit la hm en chaîne de caractères + // char *hm_to_str(const hm_t *const hm); + // // affiche le contenu de la hm + // void hm_print(const hm_t *const hm); +} \ No newline at end of file