Skip to content

Commit ce42e44

Browse files
authored
Merge pull request #1 from fedacking/Patch-Feda
Add files via upload
2 parents 0e26857 + 33a3631 commit ce42e44

File tree

5 files changed

+571
-23
lines changed

5 files changed

+571
-23
lines changed

hash.c

Lines changed: 175 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
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

2023
typedef 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

3740
unsigned 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+
88217
size_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
* *****************************************************************/
96247
size_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

141292
bool 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

184336
void hash_iter_destruir(hash_iter_t* iter) {

0 commit comments

Comments
 (0)