Documentos de Académico
Documentos de Profesional
Documentos de Cultura
9. 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
http://ict.udlap.mx/people/carlos/is215/ir09.html 1/14
26/1/2019 Hashing
No hay una relación aparente entre la llave y la localización del registro correspondiente
El Hash permite que 2 llaves puedan producir la misma salida --> direcciones iguales, a esto se
le conoce como "colisión". Existen distintos grados de colisiones Figura 9.2
Figura 9.2
9.3 Colisiones
http://ict.udlap.mx/people/carlos/is215/ir09.html 2/14
26/1/2019 Hashing
A simple vista notamos que nuestra función de hash es pobre ya que fácilmente habrán llaves que
generen la misma dirección ej (OLIVIER), a éstas llaves que generan las mismas direcciones se les
llama "sinónimas".
Propagar los registros: Buscar funciones que distribuyan muy aleatoriamente los registros
podemos evitar "agrupaciones" de llaves que produzcan las mismas direcciones
Usar memoria extra: En el ejemplo anterior planteamos tener una dirección de entre 1000
posibles, el uso de memoria extra se basa en proponer un espacio de direcciones posibles
mucho más grande que el número de registros a usar, de modo que si vamos a insertar 100
registros un espacio de 500 direcciones nos una mejor opción de esparcir mejor.
Colocar más de un registro en una dirección: A diferencia de los casos anteriores donde
cada dirección almacena únicamente un registro, este concepto se basa en "buckets" o cubetas
de datos en cada dirección, ahí se colocan algunos (casi todos) los registros que colisionan de
manera que al hacer una búsqueda debemos recuperar la cubeta entera y ahi buscar por el
registro deseado.
No existe una fórmula "única" para hash, pero el producirla es un algoritmo que
básicamente se presenta en 3 pasos:
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
http://ict.udlap.mx/people/carlos/is215/ir09.html 3/14
26/1/2019 Hashing
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
Existen innumerables operaciones adicionales que pueden aplicarse en las fórmulas, así
como las técnicas para limitar el valor final. Entre ellas se encuentran: elevar a alguna
potencia, raíz cuadrada, convertir los números de base (hexadecimal, octal) , etc...
La Distribución e Poisson
Probabilidad de que la dirección "b" sea escogida
p(B) = b = 1/ N
http://ict.udlap.mx/people/carlos/is215/ir09.html 4/14
26/1/2019 Hashing
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)
Si tenemos por ejemplo un archivo donde estamos considerando 100 direcciones (espacios) y
tenemos 75 registros entonces la densidad será de:
75 / 100 = 0.75 = 75 %
Este valor no nos indica el porcentaje de espacio en el archivo real, es solo la relación entre el espacio
físico y el de direcciones, mientras más densa sea la relación mayor será el número de
colisiones
http://ict.udlap.mx/people/carlos/is215/ir09.html 5/14
26/1/2019 Hashing
En caso contrario se busca la primer dirección subsecuente que esté disponible y ahí se inserta
Es importante recordar que nuestro archivo puede (debe en muchos casos) tener un número fijo
de direcciones posibles, de manera que si alcanzamos ese número máximo de direcciones
entonces debemos buscar un espacio disponible desde el inicio del archivo. Si no queda ninguno
entonces quizás tuvimos un error en nuestros cálculos y planeación del archivo.
Nota: con espacio disponible nos referimos a un espacio "reutilizado" o bien a un espacio vacío,
considerando que al eliminar un registro lo que hacemos es reutilizar su espacio.
Figura 9.3
A parte de esa dirección empezamos a buscar por el registro deseado o un espacio vacío
http://ict.udlap.mx/people/carlos/is215/ir09.html 6/14
26/1/2019 Hashing
Figura 9.4
La idea es muy similar a la que se presentó en la sección anterior, sólo existen algunas diferencias
notables:
Green... Hall...
Jenks...
King... Land... Marks...
Figura 9.5
http://ict.udlap.mx/people/carlos/is215/ir09.html 7/14
26/1/2019 Hashing
Respecto a las fórmulas de distribución la expresión de Poisson permanece intacta ya que el cálculo
es igual solo que aquí nos interesa tener un mayor número de colisiones por dirección.
Por otro lado para la densidad si tendremos una ligera variación, de manera que el cálculo ahora se
obtendrá como:
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.
http://ict.udlap.mx/people/carlos/is215/ir09.html 8/14
26/1/2019 Hashing
Figura 9.6
Figura 9.7
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
En la sección 9.3 se mencionaron varias técnicas relacionadas con Hash y el manejo de colisiones,
dichas técnicas se basan en una estructura estática, es decir, se calcula un cierto número de
posiciones posibles (registros) y en base a este supuesto se amplía el espacio de direcciones y en
consecuencia se disminuyen las colisiones.
Desafortunadamente este esquema "estático" no es muy adecuado para la mayoría de las
aplicaciones ya que normalmente no se tiene un estimado del número de registros que se
almacenarán, de manera que se requiere una estructura también basada en Hash pero que sea más
dinámica de modo que permita "crecer" y adecuarse a cualquier número de elementos; así surge el
Hash Extendido.
El algoritmo de Hash Extendido se basa en una estructura de recuperación conocida como "trie", la
cual se encuentra dentro del grupo de búsquedas por radio, esto debido a que se presenta un árbol
donde cada rama presenta un radio de posibilidades hacia donde moverse. en la figura 9.9 tenemos
un radio de 26 que son las letras del alfabeto.
Figura 9.9
De manera que el "radio" definirá el número de ramas posibles desde cada nodo, en la figura 9.10 el
radio es igual a 10 ya que únicamente emplea números.
http://ict.udlap.mx/people/carlos/is215/ir09.html 10/14
26/1/2019 Hashing
Figura 9.10
Para el caso del hash extendido, el trie que se emplea es de radio 2, utilizando como valores posibles
el 1 y el 0, significando un bit. De manera que las decisiones de "a qué rama moverse" se definirá
como una decisión bit por bit. Así, si buscamos alguna llave cuyo hash produce una dirección empieza
con "11" entonces recuperaremos la "cubeta C".
Figura 9.11
Como se puede observar le "trie" es una estructura en forma de árbol, pero si tratamos de manejarlo
como tal tendremos un caso similar al indexamiento tradicional resultando la mejor solución en un B-
Tree. Así que para poder aprovechar los beneficios del trie lo que se hace es representarlo a manera
de arreglo de registros (cubetas en la mayoría de los casos) contiguos, al cual se le conoce como
"directorio".
Para convertir el trie a directorio lo primero que se debe hacer es representar el árbol como una
estructura completa donde existan al mismo nivel el máximo número de hojas posible (Figura 9.12a),
posteriormente elaboramos el arreglo en un archivo de manera que utilicemos todo el rango de
direcciones posibles (00,01,10,11) donde cada dirección contendrá un apuntador a la cubeta
correspondiente.
http://ict.udlap.mx/people/carlos/is215/ir09.html 11/14
26/1/2019 Hashing
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).
http://ict.udlap.mx/people/carlos/is215/ir09.html 12/14
26/1/2019 Hashing
Figura 9.14
En esta sección se omiten los detalles de implementación, pero cabe mencionar algunos de ellos:
Las direcciones obtenidas por el hash suelen leerse de derecha a izquierda, ejemplo:
Supongamos que vamos a ingresar la llave 45 y su hash nos da 000 0010 1110 0011,
naturalmente a la izquierda siempre tendremos muchos 0s así que tendríamos muchas
colisiones para esos valores así que se opta por empezar a la derecha, de modo que
tendríamos 1100 0111 0100 0000, y por lo tanto la llave se almacenaría en la cubeta "C"
Concluyendo:
http://ict.udlap.mx/people/carlos/is215/ir09.html 13/14
26/1/2019 Hashing
El Hash tradicional es muy eficiente pero tiene 2 problemas principales: colisiones y el hecho de
ser estático
El Hash extendido es una estructura relativamente moderna que promete ser mejor que el B-
Tree, desafortunadamente existen algunas deficiencias que lo limitan, entre ellas:
http://ict.udlap.mx/people/carlos/is215/ir09.html 14/14