You are on page 1of 21

Tablas HASH

Agustn J. Gonzlez
ELO320: Estructura de Datos y
Algoritmos

Introduccin

Muchas aplicaciones requieren un conjunto dinmico que soporte las


operaciones de un diccionario: Insert, Search, Delete. Por ejemplo el compilador
cuando guarda los identificadores de un programa.
Es posible hacer uso de una lista enlazada con un tiempo O(n) ; sin embargo,
este tiempo se puede reducir notablemente a orden O(1) en la mayora de los
casos usando una tabla hash.
La idea surge de los arreglos que permiten acceso a sus elementos en orden
O(1).
Una opcin sera usar un arreglo tan grande como el rango de posibles claves.
La desventaja es el espacio de memoria requerido en tal estrategia.
Otra opcin es usar un arreglo menor, al cual podemos mapear las claves en
uso. Esta funcin de mapeo es la funcin hash. La tabla as organizada es la
tabla hash.
Como es posible que dos claves conduzcan al mismo mapeo (lo cual se conoce
como una colisin), es necesario buscar formas para resolver esta situacin.
Una forma, conocida como hashing abierto (hay otros trminos dependiendo del
texto), crear una lista asociada a cada entrada del arreglo.
Otra forma, conocida como hashing cerrado (el trmino depende del libro),
almacena las claves en las mismas entradas del arreglo o tabla hash.

Visin grfica (hashing abierto)

Desde un gran Universo slo un nmero


reducido de claves sern consideradas.
Universo de Claves

Claves usadas

Funcin de mapeo
o Funcin de hash

Lista Enlazada

Visin grfica (hashing cerrado)

Desde un gran Universo slo un nmero


reducido de claves sern consideradas.
Universo de Claves

Claves usadas

La lista se almacena
en la misma tabla
Funcin de mapeo
Funcin de hash

Hashing Abierto

Suposicin de hashing uniforme: es cuando cualquier elemento es igualmente


probable de caer en cualquiera de las m entradas de la tabla hash,
independientemente de cualquier otro elemento.
An con hashing uniforme, el peor caso de hashing abierto nos conduce a una lista
con todas las claves en una nica lista. El peor caso para bsqueda es as (n).
En hashing abierto la bsqueda no exitosa de una clave toma tiempo (1+) en
promedio, donde es el factor de carga =nmero de claves en la
tabla/nmero de entradas en la tabla hash.
Por qu esto? El costo de calcular la funcin hash (1), ms la prueba en cada
una de los nodos de la lista asociada a la entrada. En promedio hay n/m nodos en
cada lista y hay que probarlos todos ==> (). Luego se tiene que el tiempo total
es (1+).
Anlogamente la bsqueda exitosa de una clave toma un tiempo
(1+/2)=(1+), en el texto hay un clculo ms preciso.
La insercin de una clave toma (1).
2
2
2n
La eliminacin de una clave toma un tiempo (1+). Aqu suponemos que la clave
debe ser buscada dentro de la lista, para luego ser eliminada.
En resumen, si la tabla mantiene un nmero limitado de claves, n/m est acotado
por una constante, todas las operaciones toman un tiempo (1).

Funciones Hash

Una buena funcin hash debera satisfacer la suposicin de


hash uniforme.
Como el recorrido de la funcin de hash es un nmero
natural, hay que saber interpretar o transformar a nmero
natural el tipo de clave.
Si se trata de claves enteras, el problema est ms o menos
resuelto.
Si se trata de secuencia de caracteres, strings, se puede
interpretar cada carcter como un nmero en base 128 (los
nmeros ASCII van del 0 al 127) y el string completo como un
nmero en base 128. As por ejemplo la clave pt puede
ser transformada a (112*128+116)=14452. OBS:
ASCII(p)=112 y ASCII(t)=116. Otra opcin es sumar
caracteres de a dos agrupados formando nmeros de 16 bits.
En adelante supondremos que las claves son nmeros
naturales (o ya han sido transformadas a nmeros naturales)

Funciones Hash: Mtodo de Divisin

Mtodo de divisin:
Este mtodo consiste en tomar el resto de la
divisin por m, el nmero de entradas de la tabla.
As
h(k) = k mod m
En C sera h(k) = k % m;
Usar m = una potencia de 2, no es buena idea, ya
que el valor de hash queda dependiendo de slo
los bits menos significativos de k.
Una forma de hacer hash(k) dependiente de todos
los bits menos significativos es usar nmero
primos no muy cercanos a una potencia de dos.

Funciones Hash: Mtodo de


Multiplicacin

Este mtodo opera en dos pasos. Primero, multiplicamos la clave por una
constante A en el rango 0 < A < 1 y extraemos la parte fraccionaria de
k*A. Segundo, Multiplicamos este valor por el nmero de entradas de la
tabla y tomamos el piso del (o truncamos el) resultado.
En resumen:
h(k) = m *(k*A mod 1)
Donde mod 1 debe ser interpretado como k*A - k*A
Cmo se hace en C? Ver man modf. Tambin es til man -k fraction
#include <math.h>
double modf(double x, double *iptr);
Description: The modf() function breaks the argument x into an integral
part and a fractional part, each of which has the same sign as x. The
integral part is stored in iptr. The modf() function returns the fractional
part of x.
Una ventaja de este mtodo es que el valor de m no es crtico.
El mtodo trabaja bien con cualquier valor de A, pero trabaja mejor con
algunos valores que otros, por ejemplo A~(sqrt(5)-1)/2 es recomendado.
As para m =10000, h(123456) = 10000 *(123456*0.61803.. mod 1) =41

Hashing Cerrado

En Hashing cerrado, todos los elementos o claves son


almacenadas en la misma tabla hash. Es decir, cada
entrada de la tabla contiene un elemento del conjunto
dinmico o NULL.
Cuando se busca, examinamos varias entradas hasta
encontrar lo buscado o bien es claro que no est.
No hay una lista ni elementos almacenados fuera de la
tabla.
La tabla se podra llenar. El factor de carga no puede
exceder 1.
La gran ventaja de hashing cerrado es que elimina
totalmente los punteros usados en la lista enlazada. Se
libera as espacio de memoria, el que puede ser usado en
ms entradas de la tabla y menor nmero de colisiones.

Hashing Cerrado

La insercin se efecta probando la tabla hasta encontrar un espacio vaco.


La funcin de hash usa un segundo argumento, el nmero de la prueba.
h: U x { 0, 1, 2, .. , m-1} ----> {0, 1, 2, ... m-1}
Para una clave k se prueban sucesivamente: h(k,0) , h(k,1), .. h(k,m-1)

Hash_Insert(T, k) {
/* pseudo cdigo */
int i,j;
for (i = 0; i<m; i++) {
j=h(k,i);
if (T[j] == NULL){
T[j]=k;
return;
}
}
printf( hash overflow);
}

int Hash_Search(T, k) {
/* pseudo cdigo*/
int i,j;
for (i = 0; i<m; i++) {
j=h(k,i);
if (T[j] == NULL)
return -1;
else if (T[j] == k)
return j;
}
}

10

Funciones de Hash h(k,i)

Existen al menos dos formas para definir esta funcin:


prueba lineal y doble hashing.
Prueba lineal
La funcin es:
h(k,i) = (h(k) +i) mod m
Una desventaja de este mtodo es la tendencia a crear
largas secuencias de entradas ocupadas,
incrementando el tiempo de insercin y bsqueda.
Doble hashing
La funcin es:
h(k,i) = (h1(k) + i*h2(k)) mod m
Por ejemplo h1 y h2 pueden ser:
h1 = k mod m
h2 = 1 + (k mod (m-1))

11

Ejemplo de hashing Cerrado

Sea h(k,i) = (h1(k) + i*h2(k)) mod 13; 0


con
1
h1 = k mod 13
2
h2 = 1 + (k mod 11)
3
4
5
h(79,0) = 1
6
h(72,0) = 7
7
h(98,0) = 7 colisin!
8
h(98,1) = (7+11) mod 13 =5
9
h(14,0) = 1 colisin!
h(14,1) = (1+4) mod 13 = 5 idem. 10
11
h(14,2) = (1+2*4) mod 13 = 9
12

79

69
98
72
14
50

12

Anlisis de Hashing Cerrado


(caso bsqueda no exitosa =
insercin)
El nmero de pruebas promedio en bsqueda no exitosa
en hashing cerrado es a lo ms 1/(1-). Suponemos
hashing uniforme y = factor de carga = n/m.
Este tiempo es el mismo tiempo promedio de insercin del
prximo elemento.
E[X] iP{X i}
Desarrollo:
i 0

Notar que:
i P{X i} P{ X i 1}
i 0

0 * P{X 0 } 0 * P{ X 1}
1* P{X 1 } 1* P{ X 2}
2 * P{X 2 } 2 * P{ X 3} ..
(i 1) * P{X i 1 } (i 1) * P{ X i}
i * P{X i} i * P{ X i 1} ...
P{X 1 } P{X 2 } P{X 3 } P{X 4 } P{X 5 } ...

P{X i}
i 1

13

Anlisis de Hashing Cerrado


(caso bsqueda no exitosa = insercin)
(Cont.)
El tiempo de insercin o de bsqueda no exitosa cuando la

tabla tiene factor de carga n/m se puede determinar como:


n

I 1 i * P{debamos hacer exactamente i pruebas antes de insertar}


i 0

1 P{debamos hacer al menos i pruebas antes de insertar}


i 1

1 pi
i 1

p1 n / m
n

p2

// Probabilidad que 1 celda est ocupada

n 1

n n 1
pi

m m 1

// segunda celda est ocupada dado que la primera tambin


i

n i 1 n
i
..

m i 1 m

1
Luego I 1 p i 1 1 2 3 ....
1
i 1

14

Anlisis de Hashing Cerrado (caso bsqueda


exitosa = promedio de insercin desde 1 a n)

El tiempo de bsqueda exitosa es 1 ln 1


1
Por qu? La secuencia seguida para buscar la
clave k es la misma seguida cuando k fue insertada.
Por lo tanto basta calcular el promedio de pruebas
para insertar las claves desde la primera hasta la nsima.
Si k es la (i+1)sima clave, el nmero esperado de
intentos para su insercin es 1/(1-i/m). Por lo tanto
en nmero promedio de intentos ser la suma de
todos los intentos dividida por el nmero de claves
insertadas.

15

Anlisis de Hashing Cerrado


(caso bsqueda exitosa = promedio de insercin
desde 1 a n) (cont.)
Si k es la (i+1)sima clave, el nmero esperado de intentos para
su insercin es 1/(1-i/m). Por lo tanto en nmero promedio de
intentos ser la suma de todos los intentos dividida por el
nmero
de claves
n 1
n 1 insertadas.
n 1

n i 0

1
m
m
1

n i 0 m i n i 0 m i

1 1
1
1
1
1
1

...
m m 1 m 2 m 3
m (n 1)

1 n 1 1
1

i 0 (m i )
m n 1

1 1

j m n 1 j

j m n 1 j

(1 / x)dx

mn

1 1
ln

16

Resumen Anlisis de Hashing

Hashing Abierto:

Costo
Costo
Costo
Costo

de
de
de
de

insercin = (1)
bsqueda exitosa = (1+/2)
bsqueda no exitosa = (1+)
eliminacin = (1+/2) cuando la clave est
= (1+) cuando la clave no est

Hashing Cerrado

Costo de insercin
1

1 1
ln

Costo de bsqueda exitosa 1

Costo de bsqueda no exitosa

Costo de eliminacin = costos de bsqueda

17

Ejercicio

Se desean ingresar 3/4 M elementos a una tabla de hash


cerrado inicialmente vaca y con M entradas. Qu es ms
econmico en trmino de nmero de operaciones: duplicar
el tamao de la tabla hash cuando se alcance un factor de
carga de 0.5 triplicar su tamao cuando el factor de
carga llega a 1/3? Incluya su desarrollo.
1
1
Caso 1 : x
*M / 2
* 3M / 4
3
M
/
4
1 0.5
1
2M
M 6 M / 5 2.2 M

1
1
*M /3
* 3M / 4
3
M
/
4
11/ 3
1
3M
0.5M M 1.5M

Caso 2 : x

18

Ejercicio

Se desean ingresar 3/4 M elementos a una tabla de hash cerrado


inicialmente vaca y con M entradas. Qu es ms econmico en
trmino de nmero de operaciones: duplicar el tamao de la
tabla hash cuando se alcance un factor de carga de 0.5 triplicar
su tamao cuando el factor de carga llega a 1/3? Incluya su
desarrollo.
Caso 1) Tiene dos partes: Primero llenar tabla M hasta 50%,
luego llenar
1 2M
con 3M/4
1
1 tabla
1 claves.

ln

1 1

* M / 2

ln

* 3M / 4

12

3M / 4
3/8
2M
1
1
1
1
x
ln
ln
*M / 2
* 3M / 4
0.5 1 0.5
3 / 8 1 3 / 8
8 8

x 2 ln 2 * M / 2 ln * 3M / 4 M ln 2 2(3 ln 2 ln 5) M
3 5
x (7 ln 2 2 ln 5) M M ln(128 / 25) M ln(5.12)

1 0.5, 2

19

Ejercicio

Se desean ingresar 3/4 M elementos a una tabla de hash cerrado


inicialmente vaca y con M entradas. Qu es ms econmico en
trmino de nmero de operaciones: duplicar el tamao de la tabla
hash cuando se alcance un factor de carga de 0.5 triplicar su
tamao cuando el factor de carga llega a 1/3? Incluya su desarrollo.
Caso 2) Tiene dos partes: Primero llenar tabla M hasta 33%, luego
llenar tabla 3M con 3M/4 claves.

1 1
1 1
* M / 3 ln
* 3M / 4
x ln
1 1 1
2 12
3M / 4
1 1 / 3, 2
1/ 4
3M
x 3 ln 3 / 2 * M / 3 4 ln 4 / 3 * 3M / 4
3 4 3
x M ln 3 / 2 3M ln(4 / 3) M ln *
2 3

x M ln(32 / 9) M ln(3.55)
=> Mejor

caso 2 20

Divertimento

Cmo logramos dejar la basura fuera de la pala


moviendo slo dos palos?

Moviendo tres palos, cmo dejamos el pez


mirando lacia el lado opuesto?

21