55#include "lista.h"
66#include "hash.h"
77
8- #define CAPACIDAD_INICIAL 10
8+ #define CAPACIDAD_INICIAL 8
9+ #define MAX_ESPACIO_USADO 2
10+ #define MIN_ESPACIO_USADO 0.5
11+
912
1013/* ******************************************************************
1114 * DEFINICION DE LOS TIPOS DE DATOS
@@ -18,7 +21,7 @@ struct hash {
1821};
1922
2023typedef struct nodo {
21- char * clave ;
24+ const char * clave ;
2225 void * dato ;
2326}nodo_t ;
2427
@@ -35,20 +38,19 @@ struct hash_iter {
3538//One-at-a-time hash
3639
3740unsigned long funcion_hash (const char * clave , size_t capacidad ) {
38- unsigned char * p = clave ;
39- unsigned h = 0 ;
41+ unsigned h = 0 ;
4042
41- for (int i = 0 ; i < capacidad ; i ++ ) {
42- h += p [i ];
43- h += (h << 10 );
44- h ^= (h >> 6 );
45- }
43+ for (int i = 0 ; i < capacidad ; i ++ ) {
44+ h += ( unsigned ) clave [i ];
45+ h += (h << 10 );
46+ h ^= (h >> 6 );
47+ }
4648
47- h += (h << 3 );
48- h ^= (h >> 11 );
49- h += (h << 15 );
49+ h += (h << 3 );
50+ h ^= (h >> 11 );
51+ h += (h << 15 );
5052
51- return h %capacidad ;
53+ return h %capacidad ;
5254}
5355
5456
@@ -85,16 +87,165 @@ hash_t *hash_crear(hash_destruir_dato_t destruir_dato) {
8587
8688}
8789
90+ nodo_t * crear_nodo (const char * clave ,void * dato ){
91+ nodo_t * nodo = malloc (sizeof (nodo_t ));
92+ if (!nodo ){
93+ return NULL ;
94+ }
95+ nodo -> clave = clave ;
96+ nodo -> dato = dato ;
97+
98+ return nodo ;
99+ }
100+
101+ //va a cada elemento y lo rehashe y lo guarda donde corresponde
102+ bool hash_redimensionar (hash_t * hash ,size_t new_tam ){
103+ nodo_t * nodo ;
104+ unsigned long clave_hash ;
105+ lista_t * * new_tablas = malloc (new_tam * sizeof (lista_t * ));
106+ for (int i = 0 ; i < new_tam ; i ++ ) {
107+ new_tablas [i ] = lista_crear ();
108+ }
109+ for (int i = 0 ;i < hash -> capacidad ;i ++ ){
110+ while (!lista_esta_vacia (hash -> tabla [i ])){
111+ nodo = lista_borrar_primero (hash -> tabla [i ]);
112+ clave_hash = funcion_hash (nodo -> clave ,new_tam );
113+ lista_insertar_ultimo (new_tablas [clave_hash ],nodo );
114+ }
115+ lista_destruir (hash -> tabla [i ], NULL );
116+ }
117+ hash -> capacidad = new_tam ;
118+ free (hash -> tabla );
119+ hash -> tabla = new_tablas ;
120+ return true;
121+ }
122+
123+ /* Guarda un elemento en el hash, si la clave ya se encuentra en la
124+ * estructura, la reemplaza. De no poder guardarlo devuelve false.
125+ * Pre: La estructura hash fue inicializada
126+ * Post: Se almacenó el par (clave, dato)
127+ */
128+ bool hash_guardar (hash_t * hash , const char * clave , void * dato ){
129+ // Si nos pasamos del limite hay que redimensionarlo
130+ if (hash -> cantidad /hash -> capacidad > MAX_ESPACIO_USADO ){
131+ if (!hash_redimensionar (hash ,hash -> capacidad * 2 )){
132+ return false;
133+ }
134+ }
135+ unsigned long clave_hash = funcion_hash (clave ,hash -> capacidad );
136+ nodo_t * nodo = crear_nodo (clave ,dato );
137+ if (!lista_insertar_ultimo (hash -> tabla [clave_hash ],nodo )){
138+ //si fallo al insertarlo por algun motivo
139+ return false;
140+ }
141+ hash -> cantidad ++ ;
142+
143+ return true;
144+ }
145+
146+ /* Borra un elemento del hash y devuelve el dato asociado. Devuelve
147+ * NULL si el dato no estaba.
148+ * Pre: La estructura hash fue inicializada
149+ * Post: El elemento fue borrado de la estructura y se lo devolvió,
150+ * en el caso de que estuviera guardado.
151+ */
152+ void * hash_borrar (hash_t * hash , const char * clave ){
153+ // Si nos pasamos del limite hay que redimensionarlo
154+ if (hash -> cantidad /hash -> capacidad < MIN_ESPACIO_USADO && hash -> capacidad > CAPACIDAD_INICIAL ){
155+ if (!hash_redimensionar (hash ,hash -> capacidad /2 )){
156+ return NULL ;
157+ }
158+ }
159+ unsigned long clave_hash = funcion_hash (clave ,hash -> capacidad );
160+ lista_iter_t * iter = lista_iter_crear (hash -> tabla [clave_hash ]);
161+ nodo_t * nodo = lista_iter_ver_actual (iter );
162+ while (!lista_iter_al_final (iter ) && nodo -> clave != clave ){
163+ //iterar hasta encontrar la clave
164+ nodo = lista_iter_ver_actual (iter );
165+ lista_iter_avanzar (iter );
166+ }
167+ if (lista_iter_al_final (iter )){
168+ return NULL ;
169+ }
170+ nodo = lista_iter_borrar (iter );
171+ void * dato = nodo -> dato ;
172+ free (nodo );
173+ lista_iter_destruir (iter );
174+ hash -> cantidad -- ;
175+
176+ return dato ;
177+ }
178+
179+ /* Obtiene el valor de un elemento del hash, si la clave no se encuentra
180+ * devuelve NULL.
181+ * Pre: La estructura hash fue inicializada
182+ */
183+ void * hash_obtener (const hash_t * hash , const char * clave ){
184+ unsigned long clave_hash = funcion_hash (clave ,hash -> capacidad );
185+ lista_iter_t * iter = lista_iter_crear (hash -> tabla [clave_hash ]);
186+ nodo_t * nodo = lista_iter_ver_actual (iter );
187+ while (!lista_iter_al_final (iter ) && nodo -> clave != clave ){
188+ //iterar hasta encontrar la clave
189+ nodo = lista_iter_ver_actual (iter );
190+ lista_iter_avanzar (iter );
191+ }
192+ if (lista_iter_al_final (iter )){
193+ return NULL ;
194+ }
195+ lista_iter_destruir (iter );
196+ return nodo -> dato ;
197+ }
198+
199+ /* Determina si clave pertenece o no al hash.
200+ * Pre: La estructura hash fue inicializada
201+ */
202+ bool hash_pertenece (const hash_t * hash , const char * clave ){
203+ unsigned long clave_hash = funcion_hash (clave ,hash -> capacidad );
204+ lista_iter_t * iter = lista_iter_crear (hash -> tabla [clave_hash ]);
205+ nodo_t * nodo ;
206+ while (!lista_iter_al_final (iter )){
207+ nodo = lista_iter_ver_actual (iter );
208+ if (nodo -> clave == clave ){
209+ return true;
210+ }
211+ //iterar hasta encontrar la clave
212+ lista_iter_avanzar (iter );
213+ }
214+ return false;
215+ }
216+
88217size_t hash_cantidad (const hash_t * hash ) {
89218 return hash -> cantidad ;
90219}
91220
221+ void destruir_nodo (void * nodo ,void destruir_dato (void * )){
222+ nodo_t * nodo_cast = nodo ;
223+ if (destruir_dato ){
224+ destruir_dato (nodo_cast -> dato );
225+ }
226+ free (nodo );
227+ }
228+
229+ /* Destruye la estructura liberando la memoria pedida y llamando a la función
230+ * destruir para cada par (clave, dato).
231+ * Pre: La estructura hash fue inicializada
232+ * Post: La estructura hash fue destruida
233+ */
234+ void hash_destruir (hash_t * hash ){
235+ for (int i = 0 ; i < hash -> capacidad ;i ++ ){
236+ while (!lista_esta_vacia (hash -> tabla [i ])){
237+ destruir_nodo (lista_borrar_primero (hash -> tabla [i ]),hash -> destruir_dato );
238+ }
239+ }
240+ }
241+
242+
92243
93244/* ******************************************************************
94245 * PRIMITIVAS DEL ITERADOR
95246 * *****************************************************************/
96247size_t siguiente_posicion_con_elementos (const hash_t * hash , size_t pos ) {
97- while (lista_esta_vacia ( hash -> tabla [ pos ]) && pos < hash -> capacidad ) {
248+ while (pos < hash -> capacidad && lista_esta_vacia ( hash -> tabla [ pos ]) ) {
98249 pos ++ ;
99250 }
100251
@@ -120,17 +271,17 @@ hash_iter_t *hash_iter_crear(const hash_t *hash) {
120271 } else {
121272 //si tiene elementos busca la primera lista que tenga elementos
122273 //le asigna la posicion de esa lista en el haintsh y crea el iterador de esa lista
123- int i = 0 ;
274+ size_t i = 0 ;
124275
125276 /*
126- while(lista_esta_vacia(hash->tabla[i]) && i < hash->capacidad) {
127- i++;
128- }
129-
130- iterador->pos = i;
277+ while(lista_esta_vacia(hash->tabla[i]) && i < hash->capacidad) {
278+ i++;
279+ }
280+
281+ iterador->pos = i;
131282 */
132283 iterador -> pos = siguiente_posicion_con_elementos (hash ,i );
133- iterador -> iter_actual = lista_iter_crear (hash -> tabla [i ]);
284+ iterador -> iter_actual = lista_iter_crear (hash -> tabla [iterador -> pos ]);
134285
135286 }
136287
@@ -140,7 +291,7 @@ hash_iter_t *hash_iter_crear(const hash_t *hash) {
140291
141292bool hash_iter_al_final (const hash_iter_t * iter ){
142293 size_t siguiente_lista = siguiente_posicion_con_elementos (iter -> hash , iter -> pos );
143- if ((iter -> pos == siguiente_lista ) || (iter -> hash -> cantidad == 0 )){
294+ if ((iter -> hash -> cantidad == 0 ) || (iter -> pos == siguiente_lista )){
144295 return true;
145296 }
146297 return false;
@@ -177,8 +328,9 @@ const char *hash_iter_ver_actual(const hash_iter_t *iter) {
177328 if (hash_iter_al_final (iter )){
178329 return NULL ;
179330 }
331+ nodo_t * actual = lista_iter_ver_actual (iter -> iter_actual );
180332
181- return iter -> iter_actual -> actual -> clave ;
333+ return actual -> clave ;
182334}
183335
184336void hash_iter_destruir (hash_iter_t * iter ) {
0 commit comments