2. HASHING
En una búsqueda en un listado ordenado, podemos utilizar el “BinarySearch” que básicamente
divide el listado y si los valores son mayores de la mitad del listado sólo buscará en una
mitad de todo el listado, lo mismo si son menores.
El Hasing es un proceso similar de búsqueda pero mejorado, ya que a cada valor se le asigna
un slot o una posición específica donde sea más facil localizarlo.
Para ésto se utiliza un Hash Table. La misma tiene unos espacios o posiciones definidas pero
vacías donde podemos almacenar los items.
3. HASHING
Hash Function o la Función de Hash es el mapeo que hay entre el item que se almacenará y el
valor Hash. Para ésto si, por ejemplo, los items son números el valor hash será comúnmente, el
residuo del item y del largo de la lista. Ejemplo: tenemos los items 54,26,93,17,77,31…y si
el largo de nuestra colección sea 11, el Valor Hash sería el residuo de 54/11 en la primera
posición.
Item
Valor Hash
54
10
26
4
93
5
17
6
77
0
31
9
4. HASHING
Es decir, en la posición 10 encontramos el valor o el item 54 como vemos en
la siguiente imagen. Ásí mismo, sucede con los otros item almacenados en el valor hash.
Pero tenemos un problema. Suponiendo que tenemos un item 44 al aplicarle la fórmula para
que nos quede el valor hash 44/11 el residuo será 0 y la posición 0 ya está ocupada por el
item 77 y los valores hash deben ser únicos ya que mediante ese valor es que nuestra
búsqueda es correcta y efectiva. Ésto es conocido como collision (colisión), cuando dos
items reclaman la misma posición.
5. HASHING
Una función perfecta de hash es la que no tiene colisión o que tengan las mínimas colisiones.
El llamado folding method es una función hash que minimiza la posibilidad de colisiones. Trabaja dividiendo
el item en las mismas partes posibles, por ejemplo, si nuestra colección queremos almacenar un
número de teléfono 787-558-9856, la función lo que hace es dividirla o separarla en pares
78+75+58+98+56 y sumarlas = 365. El total se le aplicaría la misma fórmula de dividirla entre el número
de slots o espacios de la colección por ejemplo 11 y el residuo sería ese espacio en la colección.
En este caso sería 365/11 y el residuo sería 2 por lo que el número de teléfono 787-558-9856 estaría
almacenado en el slot 2 de la colección.
Otra función hash es mid-square method donde se exponenciará a dos el ítem y los dos
dígitos del medio del número se extraen, se aplica la división del número de slots
y su residuo. Ejemplo 44 a la 2 = 1,936 el 93 se divide entre 11 y su residuo es 5.
Así nos quedaría el hash table.
Item
Residuo
Mid-Square
54
10
3
26
4
7
93
5
9
17
6
8
77
0
4
31
9
6
6. HASHING
¿Cómo se podrían almacenar caracteres o palabras? En otras palabras, cómo almacenaríamos
un string?. Podríamos solucionarlo separando la palabra por sus letras y sacar el valor
decimal de ascii. Una vez con el valor decimal de cada letra la sumamos y aplicamos las
funciones que hemos mostrado con anterioridad. Veamos el siguiente ejemplo.
7. HASHING
Ahora bien, ¿cómo resolvemos el problema de la colisión? Según hemos visto anteriormente,
cuando dos o más ítems reclaman posicionarse en el mismo lugar dentro de la tabla hash, se
produce una colisión. Además, vimos que una función perfecta es la que carece de estas
colisiones. Entramos ahora a un método llamado collisión resolution ó resolución de colisiones.
Veamos primero open addressing. Este método intentará, buscarle un espacio vació a ese ítem
cuando ocurra una colisión. Al visitar sistemáticamente cada espacio a la vez esto se llama linear
probing. En nuestro ejemplo anterior nos dimos cuenta de que si quisiéramos almacenar el 44, no
daría la misma posición del 77, o sea la posición 0.
Open addressing lo resolvería buscándole un espacio vacío al 44 como aparece en la imagen.
8. HASHING
Uno de los problemas que podremos encontrar al saltar una posición como lo hace el linear
probing es el clustering que pueden aparecer más colisiones en el mismo valor de hash
acumulándose.
Una de técnicas que podemos utilizar es saltar los espacios utilizando el plus 3 o también
conocido como rehashing y consiste en la posición donde ocurrió la colisión a la cual se la
sumará 1, se dividirá entre el tamaño de la colección y se sacará el residuo.
Rehash(pos) = (pos + 3)%tamaño de la tabla hash
9. HASHING
Un método más, sería quadratic probing que creará cuadrados perfectos. Esto quiere decir que
cuando aparezca una colisión incrementará dos, por ejemplo 1,3,5,7,9…o sea, el primer valor
hash «h» los sucesivos serán h+1, h+4, h+9, h+16…como se muestra en la siguiente imagen.
El último método que veremos es el de Chaining. Este método permite colocar todos los ítems
colisionados en la misma posición. El problema es que la búsqueda sería más difícil ya que
cada vez que se colisione se agregará un ítem más a la posición haciendo esto más complicado.
10. HASHING
Veamos cómo trabaja la función de hash en
Python. El tamaño de la tabla hash será de 11
y almacenaremos unos datos. Mostraremos
los espacios utilizados o sea los valores hash y
los ítems almacenados.