Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Hashing
9.1 Introducción
El origen de los algoritmos de hash es la ambición de los científicos por
encontrar una forma más rápida de encontrar la información
9.2 Definición
Una función de Hash es una caja negra que tiene como entrada una llave
y como salida una dirección
h(K)=address
Ejemplo: h(LOWELL)=4
Figura 9.1
9.3 Colisiones
LOWELL= L O W E L L _ _ _ _ _ _
76 79 87 69 76 76 32 32 32 32 32 32
2) Plegar y Agregar
Combinar algunos de estos números para generar pequeños trozos con
los que podamos trabajar
76 79 | 87 69 | 76 76 | 32 32 | 32 32 | 32 32
De manera que podemos hacer algunas operaciones matemáticas con
dichos números para finalmente obtener un número del cual
obtendremos la dirección
a= s mod n
p(B) = b = 1/ N
p(BB)= b x b
x!
p(2)= 0.184
p(3)= 0.061
p(4)= 0.015
Por otro lado si tenemos N direcciones, el número de direcciones con x
colisiones será:
Np(x)
75 / 100 = 0.75 = 75 %
Figura 9.3
Figura 9.4
Green... Hall...
Jenks...
King... Land... Marks...
Figura 9.5
r = Número de registros
bN Registros por cubeta X Número de
espacios o direcciones
a) Double Hashing
Esta técnica se basa en la idea de generar otro hash, quizás con un
formula diferente.
De manera que si el hash de una llave nos da por ejemplo 5 y ya existe
un registro en esa posición entonces se vuelve a aplicar otro hash que
nos de una dirección más dispersa por ejemplo 505 y de alguna manera
nos garantice menos colisiones. Es importante aclarar que este método
no eliminar las colisiones solo no ayuda a encontrar más rapidamente un
registro en un espacio donde de antemano sabemos que existe este
problema.
Figura 9.6
d) Scatter Tables
La idea es parecida a la anterior sólo que aquí no existe un área primaria
de datos, sólo apuntadores hacia distintas cabeceras de listas donde
residen aquellas llaves "sinónimas" que producen la misma dirección
(figura 9.8). Los detalles de implementación pueden variar, desde
algunas no muy convenientes como el usar muchos archivos para las
diversas listas o bien el implementar en un solo archivo una "lista de
listas".
Figura 9.8
Figura 9.9
Figura 9.11
Figura 9.12
Manejando el overflow
La gran ventaja de esta estructura es que permite de una manera muy
sencilla manejar el overflow en las cubetas, supongamos que existe un
overflow en "A", gracias a que de antemano teníamos reservada una
dirección extra (la rama adicional del árbol) simplemente usamos esa
dirección para apuntar hacia la nueva cubeta "D".
Figura 9.13
Por otro lado supongamos que el overflow ahora ocurre en "B", a
diferencia del ejemplo anterior aquí no tenemos una dirección extra para
relacionar a la nueva cubeta "D". De manera que dinámicamente el trie
deberá crecer ahora a 3 bits de profundidad (figura 9.14a).
Nuevamente completamos el árbol de 3 niveles para tener todas las hojas
completas (figura 9.14b) y para formar el directorio debemos hacer un
"ajuste" de manera que ahora el rango de direcciones irá de 000 hasta
111 (Figura 9.14c).
Figura 9.14
En esta sección se omiten los detalles de implementación, pero cabe
mencionar algunos de ellos:
Concluyendo: