tema 2 diccionarios. tablas hash
DESCRIPTION
Introducción a tablas hashTRANSCRIPT
Análisis y Diseño de Software
Departamento de Ingeniería de Sistemas Telemáticoshttp://moodle.dit.upm.es
Tema 2c.Diccionarios. Tablas Hash
Carlos A. Iglesias <[email protected]>
Diccionarios. Tablas Hash 2
Teoría
Ejercicio práctico en el ordenador
Ampliación de conocimientos
Lectura / Vídeo / Podcast
Práctica libre / Experimentación
Explicación en pizarra
Leyenda
Diccionarios. Tablas Hash 3
Bibliografía
● Beginning Algorithms, Simon Harris and James Ross, Wrox, 2005.
● Capítulo 11
http://proquest.safaribooksonline.com/book/software-e
ngineering-and-development/algorithms/9780764596742
Diccionarios. Tablas Hash 4
Temario
● Tablas Hash
● Direccionamiento abierto y cerrado
● Implementación de diccionario con Hash
● Complejidad en tablas hash
Diccionarios. Tablas Hash 5
Objetivos
● Comprender cómo funciona la estructura de datos tabla hash
● Comprender qué es una función hash
● Saber evaluar la complejidad de una tabla hash
● Aprender a implementar un diccionario con una tabla hash
Diccionarios. Tablas Hash 6
Objetivo
● Hemos visto que podíamos obtener una complejidad O(logn) de árboles de búsqueda binaria con diccionarios
● ¿Podemos reducir aún más la complejidad del diccionario?
Diccionarios. Tablas Hash 7
Tabla Hash (I)
● Guardamos valores en una tabla (array)
● A cada valor le asignamos una posición única que se calcula mediante una fórmula matemática (función hash)– No hace falta recorrer la tabla para
encontrarlo, insertarlo o borrarlo → basta aplicar la fórmula → O(1)
Diccionarios. Tablas Hash 8
Tabla Hash (II)
● Pero...– En el array habrá valores 'ocupados' y 'no
ocupados' alternados → no están los sitios libres al final, hay que buscarlos
– No guardamos de forma ordenada– Si hay claves duplicadas, se da una colisión
(dos valores con la misma clave) → ¿qué hacemos?
Diccionarios. Tablas Hash 9
Función Hash
● Toma un objeto y devuelve un 'valor hash', normalmente un entero
h
Valor HashObjeto
Diccionarios. Tablas Hash 10
Ej. Función Hash para String
● Suma de los valores de las letras (ej. a = 1, o bien ASCII)– h('elvis') = 5 + 12 + 22 + 9 + 19 = 67– h('madonna') = 13 +1+ 4 +15+14 + 14 + 1 = 62– h('sting') = 19 + 20 + 9 + 14 + 7 = 69
● Cumple que asignamos una posición del array a cada entrada
Diccionarios. Tablas Hash 11
Problemas función hash (I)
● No es eficiente almacenando → Dejamos hasta el 67 todas las posiciones vacías– → Podemos poner valores hash en un rango
con una función módulo, ej %10• h('elvis') = 67 % 10 = 7• h('madonna') = 62 % 10 = 2• h('sting') = 69 % 10 = 9
● Hay muchas colisiones, palabras que dan lo mismo. Ej. h('lives') = 67 % 10 = 7
Diccionarios. Tablas Hash 12
Problemas función hash (II)
● Intentamos que cuente la posición de la letra, para que salgan cosas diferentes
● Multiplicamos por un número primo (31) las letras antes de sumarlas
● h('elvis') = (((e * 31 + l) * 31 + v) * 31 + i) * 31 + s % 11 = 4996537 % 11 = 7
● h('madonna') = 3; h('sting') = 5; h('lives') = 8
→ Se comporta como queremos
Diccionarios. Tablas Hash 13
Problemas Función Hash (III)● Pero... si añadimos 'fred', F(hfred') = 7, que colisiona con 'elvis'● Podríamos ampliar el tamaño de la tabla (en vez de % 11, p. ej. % 17) o incluso disminuir el tamaño, pero no parece una solución buena, puede que haya colisiones● → Hay que ver cómo tratar estas colisiones. ● Dos métodos– Direccionamiento abierto (o hashing cerrado): prueba lineal– Direccionamiento cerrado (o hashing abierto): lista de valores
Diccionarios. Tablas Hash 14
Direccionamiento abierto (I)
● Busco sitio de forma lineal● h('fred') = 7 → colisión con 'elvis'● Busco siguiente → ocupado 'lives'● Busco siguiente → meto 'fred' en 9
Diccionarios. Tablas Hash 15
Direccionamiento abierto (II)
● Sup. ya he metido 'mary', h('mary') = 10● Meto 'tim', h('tim') = 9 → colisión con 'fred'● Siguiente → colisión con 'mary'● Siguiente (inicio) → meto en posición 0
Diccionarios. Tablas Hash 16
Variantes direccionamiento abierto
● Podemos definir varias formas de prueba, siendo i el número de intento de inserción de la clave
● Prueba lineal
● Prueba cuadrática
● Hashing doblesiendo h' una función hash secundaria, que no tome el valor 0, p.ej. siendo q un número primo menor que M
hi (x)=(h(x)+i)mod M
hi ( x)=(h(x)+i2)mod M
hi (x)=(h( x)+i∗h' ( x ))mod M
h' (x )=q−(xmod q)
Diccionarios. Tablas Hash 17
Análisis
● Con la lineal conseguiremos ocupar los huecos de forma consecutiva, y se forman ristras de valores y si caemos en una, hay que recorrerla hasta el final
● Con la cuadrática, los valores están menos aglomerados y hay huecos entre ellos, y es menos probable caer en una 'ristra'● Con la doble función hash, aún habrá más huecos, y habrá menos ristras que recorrer
Diccionarios. Tablas Hash 18
Ej. Prueba lineal hashCode()
● Implementación hashCode() de String
● Debemos implementar hashCode() si sobreescribimos equals() para colecciones como java.util.HashMap
Diccionarios. Tablas Hash 19
Direccionamiento cerrado
● Tenemos en una lista los que tienen la misma clave
● Búsqueda lineal en la lista.
● Podemos aumentar el tamaño de la tabla para reducir colisiones
Diccionarios. Tablas Hash 20
Factor de carga y rehashing● Factor de carga: número de valores almacenados / tamaño de la tabla
● Ej. anterior 16 / 11 = 1.45 → 145%
● Un factor de carga razonable: – 0.75, 75%, buen compromiso tiempo-espacio– Debe ser < 1.0 siempre, lo normal < 0.8
● Cuando superamos el factor de carga hacemos 'rehashing' (calcular otra vez la función hash)– Ampliamos el tamaño de la tabla– Seleccionamos otro valor de M, que será el primo más grande
inferior al tamaño de la tabla
Diccionarios. Tablas Hash 21
Complejidad● Direccionamiento abierto, sondeo– Si hay pocas colisiones → O(1)– Si hay más, tenemos que recorrer → O(n)
● Direccionamiento cerrado, listas de valores– Insertar, buscar, borrar: O(1) + O(lista)– Si la tabla tiene pocas colisiones, lista.size() = 1 → O(1)
● Es decir, o gastamos más espacio, o gastamos más tiempo. Si la tabla tiene tamaño h– T(n) → O(n/h); si h → n, O(1)– E(n) → O(h); si h → n, O(n)
Diccionarios. Tablas Hash 22
Complejidad T(n)
Algoritmo search put get remove
Búsqueda lineal O(n) O(1) O(n) O(n)
Búsqueda binaria iterativa O(logn) O(n) O(logn) O(n)
Búsqueda binaria recursiva
O(logn) O(n) O(logn) O(n)
Árbol binario de búsqueda O(logn) O(logn)
O(logn) O(logn)
Hash con listas O(1) k > N; O(N) k << N
Hash abierto con prueba O(1) si carga << 1
Diccionarios. Tablas Hash 23
Complejidad E(n)
Algoritmo search put get remove
Búsqueda lineal O(1) O(1) O(1) O(1)
Búsqueda binaria iterativa O(1) O(1) O(1) O(1)
Búsqueda binaria recursiva O(logn) O(logn) O(logn) O(logn)
Árbol binario de búsqueda O(n) O(n) O(n) O(n)
Hash abierto con prueba O(n) O(n) O(n) O(n)
Hash con listas O(n) + O(n) = O(n) O(n) O(n) O(n)
Diccionarios. Tablas Hash 26
Tiempos tabla hash
Factor de carga = 60%
Diccionarios. Tablas Hash 27
Tiempo tabla hash según factor de carga
Diccionarios. Tablas Hash 28
Ahora, a programar...
Diccionarios. Tablas Hash 29
Clases vistas
● DiccionarioHashMap.java
● DiccionarioTreeMap.java
● DiccionarioTablaHashAbierta.java
● DiccionarioTablaHashListas.java
● BancoPruebasHash1.java
● BancoPruebasHash2.java
Diccionarios. Tablas Hash 30
Tabla Hash en Java● En Java tenemos la interfaz java.utilMap<K,V>– void clear()– boolean containsKey(Object key)– boolean containsValue(Object value)– Collection<V> values()– Set<K> keySet()– V put(K key, V value)– V get(Object key)– V remove(Object key)– boolean isEmpty()– int size()
Diccionarios. Tablas Hash 31
Algunas implementaciones de Map<K,V>
● HashMap– Usa tabla hash con listas para colisiones– Hace un rehashing duplicando el tamaño de la tabla cuando se llena– No está sincronizada para cuando veamos concurrencia– Ofrece O(1)
● TreeMap– Es un árbol de búsqueda, mantiene los datos ordenados– No está sincronizada para cuando veamos concurrencia– Complejidad: garantiza log(n)
Diccionarios. Tablas Hash 32
Resumen
● Las tablas hash permiten obtener tiempos de O(1), si están bien dimensionadas
● Las tablas hash actúan quitan el sentido el orden en los datos
● Una función hash 'perfecta' sin colisiones es difícil de conseguir
● El compromiso tiempo / espacio es ampliar la tabla para reducir colisiones
● Las tablas hash con listas dan muy buenas prestaciones O(1)
Diccionarios. Tablas Hash 33
Ejemplo Hash - prueba
Diccionarios. Tablas Hash 34
Insertar
Diccionarios. Tablas Hash 35
Insertar (I)
Diccionarios. Tablas Hash 36
Insertar (II)
Diccionarios. Tablas Hash 37
Recuperar
Diccionarios. Tablas Hash 38
Recuperar (get)
Diccionarios. Tablas Hash 39
Borrar
Diccionarios. Tablas Hash 40
Borrar (I)
Diccionarios. Tablas Hash 41
Borrar (II)
Diccionarios. Tablas Hash 42
Tabla Hash con Listas