-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhashmap.c
More file actions
110 lines (95 loc) · 4.27 KB
/
Copy pathhashmap.c
File metadata and controls
110 lines (95 loc) · 4.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//
// Created by juanf on 2/19/2025.
// Fichero de implementación para el modulo de HashMap
//
#include <stdio.h> // Funciones estandar de entrada y salida
#include <stdlib.h> // Funciones de gestión de memoria
#include <string.h> // Funciones de manipulación de cadenas de caracteres
#include "hashmap.h" // Incluimos el fichero de cabecera del módulo
#include "errores.h" // Incluimos el fichero de cabecera de errores
// Función de hash (algoritmo djb2)
// Convierte una cadena de texto en un valor numérico para indexar en la tabla
unsigned int hash(const char *key) {
unsigned long hash = 5381; // Valor inicial para el hash
int c;
while ((c = *key++))
hash = ((hash << 5) + hash) + c; // hash * 33 + c
return hash % HASHMAP_SIZE; // Asegura que el valor esté dentro del rango de la tabla
}
// Crea un nuevo HashMap
HashMap *create_hashmap() {
HashMap *map = (HashMap *)malloc(sizeof(HashMap)); // Reservar memoria para la estructura
if (map) {
// Inicializar los buckets a NULL
for (int i = 0; i < HASHMAP_SIZE; i++) {
map->buckets[i] = NULL;
}
}
return map;
}
// Inserta un par clave-valor en el HashMap
void hashmap_put(HashMap *map, const char *key, void *value) {
unsigned int index = hash(key); // Calcular el índice usando la función de hash
// Crea un nuevo nodo para el par clave-valor
HashNode *newNode = (HashNode *)malloc(sizeof(HashNode));
if (!newNode) {
funcionDeError(ERROR_RESERVA_MEMORIA, "No se pudo reservar memoria para el nodo de la tabla hash");
}
newNode->key = strdup(key); // Copia la clave, ya que la original puede ser eliminada o modificada
newNode->value = value; // Almacena el puntero al valor
// Se implementa la resolución de colisiones mediante encadenamiento
newNode->next = map->buckets[index]; // El nuevo nodo apunta al nodo actual, anterior primer nodo
map->buckets[index] = newNode; // El nuevo nodo se convierte en el primero en la lista del bucket
}
// Recupera un valor por su clave
void *hashmap_get(HashMap *map, const char *key) {
unsigned int index = hash(key); // Calcular el índice usando la función de hash
HashNode *node = map->buckets[index]; // Obtener el primer nodo del bucket
// Buscar la clave en la lista enlazada
while (node) {
if (strcmp(node->key, key) == 0) { // Compara las claves
return node->value; // Devuelve el valor si la clave coincide
}
node = node->next; // Avanza al siguiente nodo en la lista
}
return NULL; // Retorna NULL si la clave no se encuentra
}
// Elimina un par clave-valor del HashMap
bool hashmap_remove(HashMap *map, const char *key) {
unsigned int index = hash(key); // Calcular el índice usando la función de hash
HashNode *node = map->buckets[index]; // Obtener el primer nodo del bucket
HashNode *prev = NULL; // Nodo anterior para reenlazar la lista
// Buscar la clave en la lista enlazada
while (node) {
if (strcmp(node->key, key) == 0) { // Si la clave coincide
if (prev) {
prev->next = node->next; // Desvincula el nodo, reenlazando el nodo anterior con el siguiente
} else {
map->buckets[index] = node->next; // Si es el primer nodo, actualiza el bucket
}
free(node->key); // Libera la memoria de la clave
free(node->value); // Libera la memoria del valor
free(node); // Libera la memoria del nodo
return true; // Eliminado con éxito
}
prev = node; // Actualiza el nodo anterior
node = node->next; // Avanza al siguiente nodo en la lista
}
return false; // No se encontró la clave
}
// Libera toda la memoria del HashMap
void free_hashmap(HashMap *map) {
// Recorre todos los buckets
for (int i = 0; i < HASHMAP_SIZE; i++) {
HashNode *node = map->buckets[i];
// Libera todos los nodos de la lista enlazada
while (node) {
HashNode *temp = node; // Guarda el nodo actual
node = node->next; // Avanza al siguiente nodo
free(temp->key); // Libera la clave
free(temp->value); // Libera el valor
free(temp); // Libera el nodo
}
}
free(map); // Libera la estructura del HashMap
}