Saltar a Contenido

Hashing Lineal ​

El hashing lineal provee algunas ventajas sobre el extendible. Para comenzar, requiere almacenar sólo O(1)O(1) datos en memoria, por lo que puede manejar conjuntos arbitrariamente grandes de datos. Segundo, permite controlar el porcentaje de llenado de los bloques, o bien el costo promedio de búsqueda (pero no ambos).

Pensemos primero que el archivo de hashing en disco tuviera siempre 2t2^t páginas. Un elemento yy está guardado en la página número h(y) ⁣ ⁣mod  2th(y) \!\!\mod 2^t (es decir, los tt bits más bajos de h(y)h(y)). Si algunas páginas rebalsan durante las inserciones, les creamos una lista enlazada de páginas de rebalse. Si, luego de un rebalse, notamos que el costo de búsqueda (es decir, 1 más el largo promedio de las listas de rebalse) se ha hecho demasiado alto, expandimos la tabla. Expandir significa duplicar su tamaño a 2t+12^{t+1}. Cada página ii, con 0≤i<2t0 \le i < 2^t, se recorre y sus elementos yy se reinsertan en la página h(y) ⁣ ⁣mod  2t+1h(y) \!\!\mod 2^{t+1}. Esto significa que una parte de los elementos se quedan en la página ii, mientras que otros se insertan en la página i+2ti+2^t.

El hashing lineal funciona de esa forma, pero realiza el proceso de expansión de manera gradual. En general, el archivo contiene pp páginas, con 2t≤p<2t+12^t \le p < 2^{t+1}. Inicialmente tenemos p=1p=1 páginas y t=0t=0. Las páginas 0≤i<p−2t0 \le i < p-2^t ya fueron expandidas, y repartidas entre las páginas ii e i+2ti+2^t, mientras que las páginas p−2t≤i<2tp-2^t \le i < 2^t aún no han sido expandidas.

Para buscar un elemento yy en el caso general, se calcula k←h(y) ⁣ ⁣mod  2t+1k \leftarrow h(y) \!\!\mod 2^{t+1}. Si k<pk < p, entonces se lee la página kk (y su posible lista de rebalse) para buscar la clave yy en ella, secuencialmente. Si k≥pk \ge p, sin embargo, la página kk aún no ha sido creada por el proceso de expansión, por lo cual el proceso de lectura debe realizarse en cambio en la página k←k−2tk \leftarrow k - 2^t.

Hashing Lineal

Cuando se cumple una determinada condición (por ejemplo, el costo promedio de búsqueda supera un cierto valor permitido), expandimos la siguiente página, es decir, la página p−2tp-2^t (¡que no es necesariamente la que produjo el rebalse que llevó a exceder el costo promedio de búsqueda permitido!). Esta página se lee y sus elementos yy se reinsertan en las páginas h(y) ⁣ ⁣mod  2t+1h(y) \!\!\mod 2^{t+1}, es decir, se reparten entre la misma p−2tp-2^t y la nueva página pp, que se agrega al final del archivo. Al terminar la expansión, hacemos p←p+1p \leftarrow p+1, y si resulta que p=2t+1p=2^{t+1}, entonces hemos completado una expansión y nos preparamos para la siguiente: t←t+1t \leftarrow t+1. Para eliminar un valor, éste se busca en la tabla y simplemente se elimina. En caso de estar en una lista de rebalse, puede usarse su espacio para mover un elemento desde la última página de la lista, de modo de poder liberar apenas se pueda esta última página y reducir así el tiempo promedio de búsqueda. Si se eliminan suficientes elementos, puede resultar que la tabla pueda contraerse sin que se exceda el costo promedio de búsqueda máximo permitido. Para realizar una contracción, primero se hace t←t−1t \leftarrow t-1 si p=2tp=2^t, y luego se hace p←p−1p \leftarrow p-1. Luego, se agregan todos los elementos de la página pp a la página p−2tp-2^t, procediendo a eliminar la página pp. Note que esto puede hacer rebalsar la página p−2tp-2^t, o alargar su lista de rebalse.

Note que una expansión o una contracción no necesariamente cambiarán la condición que las disparó acerca del costo promedio de búsqueda. En general es preferible, para evitar que una inserción o borrado disparen muchas expansiones o contracciones, realizar de todas maneras una sola, y dejar que la siguiente operación dispare nuevamente una expansión o contracción, hasta que la situación se resuelva.

Se pueden usar otros criterios en vez del máximo costo promedio de búsqueda. Por ejemplo, puede permitirse un mínimo porcentaje de llenado de las páginas, de modo de contraer cuando éste se hace demasiado bajo (y expandir cuando es posible sin violar el criterio). Este criterio se contrapone al de mantener un costo de búsqueda máximo, por lo que sólo se puede controlar uno de los dos (o puede usarse una combinación de criterios). En general el hashing lineal se comporta mejor que el extendible, aunque no suele garantizar un solo acceso por lectura.

generating algorithms by Puspito from the Noun Project. © 2026 Me. Built with VitePress.