Una tabla hash usa un array como almacenamiento principal y una función hash para traducir la clave en un índice. Cada posición del array es un bucket que puede guardar un elemento o una estructura auxiliar si hay colisiones.
class Entrada:
def __init__(self, clave=None, valor=None):
self.clave = clave
self.valor = valor
self.ocupado = clave is not None
class TablaHash:
def __init__(self, capacidad):
self.capacidad = capacidad
self.cantidad = 0
self.buckets = [Entrada() for _ in range(capacidad)]
El array buckets guarda entradas en una lista contigua, lo que facilita indexar y recorrer cuando se rehash.
La clave se transforma con la función hash en un entero, y el módulo de la capacidad define el bucket:
indice = hash_cadena(clave) % tabla.capacidad
Ese índice apunta al bucket donde se intenta insertar o buscar. Si el bucket está ocupado por otra clave, se aplica la estrategia de colisiones (que detallaremos en temas posteriores).
El tamaño inicial (capacidad) suele elegirse como potencia de dos o número primo para mejorar la dispersión. Tablas muy pequeñas generan colisiones inmediatas; tablas enormes desperdician memoria. Lo habitual es comenzar con 8, 16 o 32 buckets y crecer según el uso.
El factor de carga alpha es la relación entre elementos guardados y capacidad total:
alpha = tabla.cantidad / tabla.capacidad
Valores comunes de referencia:
Rehashing significa crear un nuevo array más grande y reinsertar cada elemento calculando de nuevo su índice. Flujo básico:
Este proceso mantiene la complejidad amortizada O(1), aunque cada rehash puntual cuesta O(n) porque se mueven todos los elementos.