Una funcion hash convierte una clave de longitud variable en un entero reducido que actua como indice dentro de una tabla. Su calidad determina la velocidad y estabilidad de estructuras como diccionarios o sets. En esta seccion repasamos sus propiedades y mostramos implementaciones sencillas en C.
Es una funcion determinista que toma una clave (entero, cadena o estructura) y devuelve un valor numerico de rango acotado. Ese valor se usa para ubicar el elemento en una tabla hash.
Se busca que todas las posiciones de la tabla reciban cantidades similares de claves. Si algunas posiciones concentran demasiados elementos, las colisiones aumentan y el tiempo promedio deja de ser O(1). Evaluar la uniformidad implica medir el factor de carga y el numero de elementos por bucket.
Para que la tabla hash funcione, la funcion debe producir siempre el mismo valor para la misma clave en todas las ejecuciones. Esto permite guardar, buscar y eliminar de forma coherente y reproducible. Variar la semilla o la formula solo se hace de manera controlada (por ejemplo al rehashing).
Para enteros suele bastar con una mezcla multiplicativa que preserve bits significativos y reduzca patrones. Ejemplo:
#define TAM_TABLA 1024
static unsigned long hash_entero(int clave) {
const unsigned long constante = 2654435761u; /* fraccion dorada en 32 bits */
unsigned long mezcla = (unsigned long)clave * constante;
return mezcla % TAM_TABLA;
}
La multiplicacion por la constante (derivada de la fraccion dorada, 232/φ ≈ 2654435761) distribuye los valores de manera casi uniforme antes del modulo.
Las cadenas requieren recorrer cada caracter y mezclarlo con el acumulador. Una variante ligera es FNV-1a, que combina XOR y multiplicacion:
#define OFFSET_BASIS 2166136261u
#define FNV_PRIME 16777619u
static unsigned long hash_cadena_fnv(const char *clave, unsigned long tam_tabla) {
unsigned long hash = OFFSET_BASIS;
int c;
while ((c = *clave++) != 0) {
hash ^= (unsigned long)c;
hash *= FNV_PRIME;
}
return hash % tam_tabla;
}
FNV-1a es rapido, determinista y mezcla bien caracteres secuenciales, lo que reduce agrupamientos al usar tablas moderadas.
Elegir o ajustar la funcion hash es un paso central para mantener el rendimiento de la tabla sin aumentar su tamaño de forma innecesaria.