Sesión 06 - Hashing
Sesión 06 - Hashing
Sesión 06 - Hashing
Robert Espinoza
0
1
2 Ana
3
4 Juan
5 Eva
6
7 Felipe
8
Operaciones básicas en tablas hash
Inserción
Para almacenar un elemento en la tabla hash se ha de
Búsqueda
Para recuperar los datos, es necesario únicamente
H ( K ) dígitos _ centrales ( K 2 )
Función hash cuadrado - Ejemplo
𝑛−1
ℎ 𝑠 = 𝑠 𝑖 . 31𝑛−1−𝑖
𝑖=0
Ejemplo
// Métodos de la Clase
@Override
Método BúsquedaPruebaLineal(A,n,clave)
pos H(clave) //Genera dirección
Si (A[pos]=clave) entonces
retorna pos //valor hallado en pos
sino
posSgte pos + 1
Mientras(posSgte<=n-1) y (A[posSgte]≠vacío) y (A[posSgte]≠clave)
y (pos≠posSgte) hacer
posSigte posSigte + 1
Si (posSigte = n)entonces
posSigte 0
Fin Si
Fin Mientras
Si (A[posSgte]=vacío) o (pos=posSgte)entonces
Retornar -1 //valor no encontrado
sino
Retornar posSigte //valor hallado en posSigte
Fin Si
Fin Método
Reasignación por Prueba Cuadrática
D + i2
Esta variación permite una mejor distribución de las
claves en colisión.
Desventaja es que existe un agrupamiento alrededor
de ciertas claves y casillas no visitadas.
Reasignación por Prueba Cuadrática -
Ejemplo
Sea A un arreglo de 10 elementos. Sean las claves 25,
43, 56, 35, 54, 13, 80, 104 y 55 asignadas según la
función hash H(K) = K mod 10
0 80
K H(K)
1 55
25 5
2
43 3
3 43
56 6
4 54
35 5
5 25
54 4
6 56
13 3
7 13
80 0
8 104
104 4
9 35
55 5
Reasignación por prueba cuadrática
Método BúsquedaPruebaCuadrática(A,n,clave)
pos H(clave) //Genera dirección
Si (A[pos]=clave) entonces
retorna pos //valor hallado en pos
sino
i1, posSgte pos + i*i, salir falso
Mientras (A[posSgte]≠vacío) y (A[posSgte]≠clave) y
(salir = falso) hacer
i i+1
posSigte pos + i*i
Si (posSigte > n-1) entonces
i 0, posSigte 0, pos 0
Mientras (A[posSgte]≠vacío) y (A[posSgte]≠clave) y
(posSigte<=n-1) hacer
i i+1
posSigte pos + i*i
fin Mientras
salir verdad
Fin Si
Fin Mientras
Reasignación por prueba cuadrática
Si (A[posSgte]=vacío)entonces
Retornar -1 //valor no encontrado
sino
Retornar posSigte //valor hallado en posSigte
Fin Si
Fin Método
Reasignación por Doble Dirección
Método BúsquedaDobleDirección(A,n,clave)
pos H(clave) //Genera dirección
Si (A[pos]=clave) entonces
retorna pos //valor hallado en pos
sino
posSgte H2(pos) //Genera dirección con segunda función Hash
Si (A[posSgte]=vacío) o (A[posSgte]≠clave)entonces
Retornar -1 //valor no encontrado
sino
Retornar posSigte //valor hallado en posSigte
Fin Si
Fin Método
Resolución de Colisiones por Arreglos
anidados
Este método consiste en que cada elemento del
arreglo tenga otro arreglo en el cual se almacenen los
elementos colisionados.
Aunque la solución parece sencilla, es ineficiente.
Al trabajar con arreglos, se depende del espacio que
tienen asignados.
Surge un problema: elegir el tamaño adecuado del
arreglo que permita un equilibrio entre el costo de
memoria y el número de valores colisionados que
puede almacenar.
Resolución de Colisiones por Arreglos
anidados - Ejemplo
Sea A un arreglo de 10 elementos. Sean las claves 25, 43,
56, 35, 54, 13, 80 y 104 asignadas según la función hash
H(K) = K mod 10.
0 80 ••• K H(K)
1 25 5
2 43 3
3 43 13 56 6
4 54 104 35 5
5 25 35 54 4
6 56 13 3
7 80 0
8 104 4
9
Resolución de Colisiones por
Encadenamiento
Consiste en que cada elemento del arreglo tenga un
apuntador a una lista enlazada.
La lista se irá generando e irá almacenando los valores
colisionados a medida que se requiera. Es el método
más eficiente.
Cualquiera que sea el número de colisiones, siempre se
puede tratar una más.
La desventaja del método es que ocupa espacio
adicional al de la tabla y requiere el manejo de listas
enlazadas.
Si las listas crecen demasiado se pierde la facilidad de
acceso directo del método hash.
Resolución de Colisiones por
Encadenamiento - Ejemplo
Sea A un arreglo de 10 elementos. Sean las claves 25, 43,
56, 35, 54, 13, 80 y 104 asignadas según la función hash
H(K) = K mod 10.
0 80 K H(K)
1 25 5
2 43 3
3 43 13 N 56 6
4 54 104 N 35 5
5 25 35 N 54 4
6 56 13 3
7 80 0
8 104 4
9
Resolución de Colisiones por
Encadenamiento
Método BúsquedaEncadenamiento(A,n,clave)
pos H(clave) //Genera dirección
Si (A[pos].dato = clave) entonces
Escribir “Clave hallada en “, pos //valor hallado en pos
sino
ptro A[pos].sigte //ptro es una variable tipo puntero
Si (ptro = NULL)entonces
Escribir “Clave no existe“ //valor no encontrado
sino
Escribir “Clave se encuentra en la lista“
Fin Si
Fin Método
Hash dinámico
Hash dinámico
T = 2i * N
Dónde:
N: Tamaño de la Tabla.
i: Número de expansiones que se quieren realizar.
T: Nuevo tamaño de la Tabla.
Métodos Totales – Expansiones totales
La densidad de ocupación se define como el cociente entre el
número de registros ocupados y el número de registros
disponibles; así se tiene que:
do = (ro/rd)*100
Dónde:
ro: Registros Ocupados.
rd: Registros Disponibles.
do: Densidad de Ocupación.
T = N / 2i
Dónde:
N: Tamaño de la Tabla.
i: Número de expansiones que se quieren realizar.
T: Nuevo tamaño de la Tabla.
Métodos Totales – Reducciones totales
Para realizar una reducción la densidad de ocupación se debe
disminuir a un valor menor al rango establecido y los registros
se deben eliminar de tal manera que los registros resultantes
se puedan ingresar en una tabla hash que posea la mitad del
tamaño de la tabla original.
Cada vez que se implementa una reducción es necesario
volver a utilizar la función hash con cada uno de los registros
almacenados.
Métodos Parciales – Expansiones
parciales
El método de las expansiones parciales consiste en
incrementar en un 50% el tamaño del arreglo establecido para
realizar la tabla hash, esta expansión se ejecuta cuando se
supera la densidad de ocupación.
Así si se tiene una tabla hash de tamaño N, al realizar la
expansión parcial se obtendrá una tabla hash de 1.5 N, al
realizar una segunda expansión se obtendrá una tabla hash de
2.25 N, al realizar una tercera expansión se obtendrá una tabla
hash de 3.375 N y en general el tamaño de la tabla para una i-
ésima expansión se define como:
T = (1.5) i * N
Dónde:
N: Tamaño de la Tabla.
i: Número de expansiones que se quieren realizar.
T: Nuevo tamaño de la Tabla.
Métodos Parciales – Expansiones
parciales
Cada vez que se pretende insertar un elemento es necesario
calcular la densidad de ocupación, si se supera esta densidad
se procede a implementar la expansión.
Al realizar cada de una de las expansiones es necesario volver
a implementar la función hash para cada uno de los registros
almacenados en la tabla hash y volver a insertarlos de nuevo
en la tabla.
Métodos Parciales – Reducciones
parciales
Este método surge como una consecuencia del método de
expansiones parciales.
En este método la densidad de ocupación disminuye de tal
manera que acepta una reducción del tamaño de la tabla hash
al 50%.
Así si se tiene una tabla hash de N, la primera reducción dará
como resultado la 0.5 N, la segunda reducción dará como
resultado 0.25 N, la tercera reducción dará 0.125 N y la i-ésima
reducción dará como resultado:
T = (0.5)i * N
Dónde:
N: Tamaño de la Tabla.
i: Número de reducciones que se quieren realizar.
T: Nuevo tamaño de la Tabla.
Métodos Parciales – Reducciones
parciales
Para realizar una reducción la densidad de ocupación debe
disminuir a un valor menor al rango establecido y los registros
se deben eliminar de tal manera que los registros resultantes
se puedan ingresar en una tabla hash que posea la mitad del
tamaño de la tabla original.
Cada vez que se implementa una reducción es necesario
volver a utilizar la función hash con cada uno de los registros
almacenados.
Búsqueda externa por dispersión
Búsqueda externa por dispersión (Hash)
0 BLOQUE 1 BLOQUE 2
1
2 BLOQUE 1
3
4
5 BLOQUE 1 BLOQUE 2 BLOQUE 3
Directorio de cubetas
Búsqueda externa por dispersión (Hash)
Bloque
Organizamos un archivo •
en cubetas que tienen un •
•
sólo bloque.
La capacidad máxima de
Bloque
cada cubeta estará •
•
determinado por el •
Bloque
Una vez que se satura la •
•
cubeta, cualquier registro •
Directorio de
asignado a ella producirá cubetas
una colisión. •
•
•
Uso de áreas independientes para
colisiones
Se definen áreas separadas (secundarias) de las
áreas primarias de almacenamiento, en las que se
almacenarán todos los registros que hayan
colisionado.
El área de colisiones puede estar organizada como
un área común a todas las cubetas.
Si se produce una colisión habrá que buscar a lo
largo del área de colisiones hasta encontrar el
elemento deseado.
Uso de áreas independientes para
colisiones
•
•
•
•
• •
• •
•
Directorio de
cubetas
•
Área de
•
colisiones
Área primaria de
almacenamiento
Uso de áreas independientes para
colisiones
Otra forma de organizar el área de colisiones es
dividirla en bloques, asociando a cada uno de ellas a
uno del área primaria.
Esta alternativa optimiza el tiempo de búsqueda en el
área de colisiones.
Sin embargo, presenta el inconveniente de que estos
bloques podrían a su vez saturarse y ocasionar
nuevamente colisiones.
Uso de áreas independientes para
colisiones
•
•
•
•
•
• •
• •
•
•
•
•
Directorio de •
•
cubetas
•
•
Área de
Área primaria de colisiones
almacenamiento
Uso de áreas de colisiones entre los
bloques de almacenamiento primario
Se definen áreas de colisiones entre los bloques de
almacenamiento primario.
Es similar al método de reasignación en la búsqueda
interna.
Una vez detectada una colisión en un bloque se debe
buscar en el área de colisiones inmediata a dicho
bloque.
Si el elemento no se encuentra y el área de colisiones
está llena, se continuará la búsqueda a través de las
otras áreas de colisiones.
El proceso termina cuando se encuentra el elemento o
cuando existen espacios vacíos en un bloque (elemento
no encontrado).
Uso de áreas de colisiones entre los
bloques de almacenamiento primario
Bloque
Bloque de colisiones
Bloque
Bloque de colisiones
•
•
•
Clave H(clave)
42 0
Porcentaje de ocupación 0 42 15
24 0
para expansión: 75% 1 24
15 1
53 1
N=4
Clave H(clave)
Porcentaje de ocupación 0 24
para expansión: 50% 42 2
1 53
24 0
2 42
15 3
3 15
53 1
Clave H(clave)
Porcentaje de ocupación 0 24 12
para expansión: 75% 21 1
1 53 21
12 0
2 42
3 15
Clave H(clave)
0 24
N=8 42 2
1
24 0
Porcentaje de ocupación 2 42
para expansión: 43.75%
15 7
3
53 5
4 12
21 5
5 53 21
12 4
6 14
14 6
7 15
Clave H(clave)
42 2
N=8 24 0
0 24 128
15 7
1 49
53 5
Porcentaje de ocupación 2 42 18
para expansión: 68.75% 21 5
3
12 4
4 12
14 6
OBS: Si tratáramos de 5 53 21
insertar 192 se 18 2
produciría una colisión 6 14 22
49 1
192 MOD 8 = 0 7 15 23
128 0
22 6
23 7
Luego de insertar la clave 23
Expansiones Totales - Ejemplo
0 128
Clave H(clave)
1 49
42 10
N = 16 2 18
24 8
3 67
15 15
4
Porcentaje de ocupación 53 5
5 53 21
para expansión: 40.62% 21 5
6 22
12 12
7 23
Porcentaje de ocupación 14 14
8 24
para reducción: 81.25% 18 2
9
49 1
10 42
128 0
11
22 6
12 12
23 7
13
Luego de insertar la 67 3
14 14
clave 67 15 15
Expansiones Totales - Ejemplo
0 128
Clave H(clave)
1 49
42 10
N = 16 2 18
D.O. para expansión > 80% 24 8
3 67
D.O. para reducción < 80% 15 15
4
53 5
5 53 21
Porcentaje de ocupación
21 5
para expansión: 40.62% 6 22
12 12
7 23
Porcentaje de ocupación 14 14
8 24
para reducción: 81.25% 18 2
9
49 1
10 42
128 0
11
22 6
Si deseamos eliminar 53 12 12
23 7
D.O. Reducción 75% < 80% 13
67 3
14 14
15 15
Expansiones Totales - Ejemplo
0 128
Clave H(clave)
1 49
42 10
N = 16 2 18
D.O. para expansión > 80% 24 8
3 67
D.O. para reducción < 80% 15 15
4
53 5
5 53 21
Porcentaje de ocupación
21 5
para expansión: 40.62% 6 22
12 12
7 23
Porcentaje de ocupación 14 14
8 24
para reducción: 81.25% 18 2
9
49 1
10 42
128 0
11
22 6
Si deseamos eliminar 53 12 12
23 7
D.O. Reducción 75% < 80% 13
67 3
14 14
15 15
Expansiones Totales - Ejemplo
Clave H(clave)
42 2
N=8
D.O. para expansión > 80% 24 0
0 24 128
D.O. para reducción < 80% 15 7
1 49
21 5
2 42 18
Porcentaje de ocupación
12 4
para expansión: 68.75% 3 67
14 6
4 12
Porcentaje de ocupación 18 2
5 21
para reducción: 150% 49 1
6 14 22
128 0
7 15 23
22 6
23 7
67 3
Luego de eliminar 53
Expansiones Parciales
2N 2N 2N
N 1.5N 2N 3N 4N 6N 8N • • •
2N 2N 2N
Expansiones Parciales - Ejemplo
Clave H(clave)
42 0
Porcentaje de ocupación 0 42 15
24 0
para expansión: 75% 1 24
15 1
53 1
N=6