estructura de datos - departamento de informáticamserrano/edi/cap6.pdf · universidad de...

32
Universidad de Valladolid Departamento de informática Campus de Segovia Estructura de datos Tema 6: Tablas de dispersión (hashing) Prof. Montserrat Serrano Montero

Upload: hacong

Post on 28-Sep-2018

214 views

Category:

Documents


0 download

TRANSCRIPT

Universidad de ValladolidDepartamento de informática

Campus de Segovia

Estructura de datosTema 6:Tablas de dispersión (hashing)

Prof. Montserrat Serrano Montero

ÍNDICE

• Conceptos básicos• Funciones hash• Implementación de tablas hash• Manejo de desbordamiento• Análisis de tablas hash

CONCEPTOS BÁSICOS• Las tablas hashing constituyen un TAD

especialmente indicado para la manipulación y almacenamiento de la información en memoria secundaria.

• Cualquier tabla es una asociación de celdas.

• Las tablas hashing son tablas que relacionan claves con posiciones de memoria donde se almacenan atributos.

• La idea básica consiste en transformar las claves en direcciones de memoria mediante una función de transformación. Estas direcciones pueden hacer referencia a memoria primaria, en cuyo caso tendríamos un array, pero en general las tablas de dispersión aprovechan su potencial para la implementación en memoria secundaria.

EJEMPLO

Supóngase que se quiere desarrollar una aplicación para registrar los participantes en un congreso. Se esperan alrededor de 3000 participantes y se requerirá almacenar los datos de cada uno, como nombre, apellidos, DNI o pasaporte, etc. Se utilizará como campo clave el primer apellido. Suponiendo que los apellidos pueden tener hasta 16 caracteres, habrá 2616 claves posibles (con un alfabeto de 26 caracteres).

Problema: Cómo asignar una clave de todas las posibles a una dirección de memoria.

Solución: Una función de transformación. Pero, ¿cómo es esa función?

CONCEPTOS BÁSICOS• Conclusión: Las tablas hashing se aplican

cuando el conjunto de claves posibles es mucho mayor que el de claves reales a almacenar.

• Definición: Dado un conjunto de claves posibles, X, y un conjunto de direcciones de memoria, D, una función de transformación, H(x), es una aplicación suprayectiva del conjunto de claves posibles en el conjunto de direcciones de memoria.

H: X → D

• Definición: El TAD tabla de dispersión es un tipo de datos homogéneo de tamaño fijo, Ttabla, compuesto por un número fijo de componentes, denominadas celdas, a las que se accede mediante una dirección de memoria resultante de una función de transformación. Sobre este TAD se definen los operadores Insertar, Buscar y Eliminar.

CONCEPTOS BÁSICOS

• Se dice que dos claves distintas x1 y x2 son sinónimas para una función de transformación H(x) si H(x1) = H(x2).

• Se dice que se ha producido un desbordamiento cuando una nueva clave se aplica a una dirección de memoria completamente ocupada.

• Se dice que se ha producido una colisióncuando dos claves distintas se aplican sobre la misma celda.

• En el caso habitual en el que una celda contiene un único registro el desbordamiento y la colisión se producen simultáneamente.

CONCEPTOS BÁSICOS• Se denomina densidad de claves al cociente

entre el número de claves en uso, m, y el número total de llaves posibles, nx.

• Se denomina factor de carga, (o densidad de carga), α, al cociente entre el número de claves en uso y el número total de registros almacenables en la tabla de dispersión. Así:

mα =

s . bdonde s es el número de registros por bloque y b es el número de bloques que hay en la tabla de dispersión.

FUNCIONES HASH

Características:a) Fáciles de calcular.b) El valor que calcula depende de la clave.c) Producir el menor nº de colisiones porque hace que la ocupación de los bloques sea equiprobable.

• Funciones uniformes que dividen el conjunto de claves posibles en grupos de claves aproximadamente iguales.

• Métodos de construcción:1. División2. Plegado3. Compresión4. Extracción5. Otros ...

FUNCIONES HASH: MÉTODO DIVISÓN

• f (x) = X mod M. a) Cuidar el elegir Mb) Espacio de direcciones: [0, M-1]

• Si el conjunto de claves es numérico y acabado en cero, no se puede elegir M = 10.

• Si las claves son cadenas de caracteres. Con M = 2 k y k ≤ 24, todas las cadenas que tengan los tres últimos caracteres iguales se asignan a la misma dirección. Esto sucede porque las potencias de M tienen divisores.Elegir M primo.

FUNCIONES HASH: MÉTODO PLEGADO

• Para las funciones de plegado: Dividir la clave en partes iguales y sumarlas. La suma de las partes puede realizarse de dos formas a) Plegado por desplazamiento.b) Plegado por las fronteras.

• El plegado por desplazamiento consiste en sumar las partes directamente.

• El plegado por las fronteras consiste en plegar el identificador por las fronteras de las partes y sumar los dígitos coincidentes.

• Si la claves es una cadena de caracteres, los dígitos de cada carácter vienen determinados por el valor decimal de la secuencia de cotejo correspondiente (ASCII, EBCDIC, etc.)

FUNCIONES HASH: MÉTODO PLEGADO

a) Cadena de ocho caracteres representada por los números de orden dentro de la secuencia de cotejo correspondiente.

b) Plegado por desplazamiento.c) Plegado en las fronteras en base decimal.d) Plegado en las fronteras en base binaria.e) Detalle del plegado en base binaria.

FUNCIONES HASH: MÉTODO COMPRESIÓN

Dividir la clave en componentes, traducir su número de cotejo a binario y aplicar la operación xor y al resultado la operación resto de división entera.

Ejemplo: C = Cadena de caracteres.C = ‘David’‘D’ = 01100100 ‘A’ = 01100001‘V’ = 01110010‘I’ = 01101001‘D’ = 01100100

01111010 = 122 mod 26 = 18

XOR

FUNCIONES HASH: MÉTODO EXTRACCIÓN

Método de la mitad del cuadrado: Si tenemos claves numéricas (si no las transformamos), calculamos su cuadrado y nos quedamos con algún número de la zona central del resultado. Nos quedamos con tantos dígitos como necesitemos para mapear el array.

Ejemplo: Array con N = 0..99C = 340 i2 = 115600 H (C) = 56C = 521 i2 = 271441 H (C) = 14

ESPECIFICACIÓN DEL TAD TABLA HASH

TAD TablaHash (VALORES: Atributos almacenados en las posiciones resultado de una transformación Hash de claves; OPERACIONES: Inicializar, Hash, Buscar, Insertar, Eliminar)Inicializar → TablaHash

Efecto: Crea una tabla hash vacía.Hash (Clave) → Posicion

Efecto: Devuelve la transformación adecuada a partir de laclave.

Buscar (TablaHash, Clave) → Atributo, BooleanEfecto: Si la clave está en la tabla, devuelve el atributocorrespondiente y un valor lógico llamado error a false. Encaso contrario error valdrá true.Excepción: Error si la clave no está en la tabla.

Insertar (TablaHash, Clave, Atributo) → TablaHash, Boolean

Efecto: Si la posición no está libre, el valor lógico error valetrue. En caso contrario en la posición Hash (clave) sealmacena el par (clave, atributo).Excepción: Error si hay colisión, desbordamiento o tabla llena.

Eliminar (TablaHash, Clave) → TablaHash, BooleanEfecto: Si la clave existe en la tabla, se deja vacía esaposición y se actualiza error a false. En caso contrario, errorvale true.Excepción: Error si la clave no está en la tabla.

Informal

Clave: Cadenas de caracteres en mayúsculas.Función hash: Primer carácter de la clave.

unit TADHash;interface const npares = ...; vacia = ...;

typecadena = ...; tatributo = ...;posicion = 1..npares;par = record

clave: cadena;atributo: tatributo;

end;TablaHash = array [posicion] of par;

procedure Inicializar (var T: TablaHash);function Hash (c: cadena): posicion;procedure Buscar (T: TablaHah; c: cadena; var

atrib: tatributo; var error: boolean);procedure Insertar (var T: TablaHash; c: cadena;

atrib: tatributo; var error: boolean);procedure Eliminar (var T: TablaHah; c: cadena;

var error: boolean);

IMPLEMENTACIÓN

procedure Inicializar;var pos: posicion;beginfor pos := 1 to npares doT [pos].clave := vacia;

end;

IMPLEMENTACIÓN

function Hash;beginHash := (ord (c [1]) – ord (‘A’) + 1

end;procedure Buscar;var pos: poscicion;beginpos := Hash (c);if T [pos].clave = c thenbeginatrib := T [pos].atributo;error := false

endelse error := true

end;

implementation

IMPLEMENTACIÓN

procedure Insertar (var T: TablaHash; c: cadena; atrib: tatributo; var error: boolean);

var pos: posicion;beginpos := Hash (c);if T [pos].clave = c then error := trueelse beginerror := false;T [pos].clave := c; {elimina claveT [pos].atributo := atrib anterior}

end;end;

IMPLEMENTACIÓNprocedure Eliminar (var T: TablaHah; c:

cadena; var error: boolean);var pos: posicion;beginpos := Hash (c);if T [pos].clave = c thenbeginerror := false;T [pos].clave := vacia

endelse error := true

end;end.

MANEJO DE DESBORDAMIENTO

• Encontrar posiciones donde ubicar el área de desbordamiento de una tabla.

• Esto puede hacerse de dos formas:a) Encadenamiento cerrado o interno.b) Encadenamiento abierto o externo.

• En el primer caso, el área de desbordamiento se ubica dentro de la tabla, comportándose como un método estático, y en el segundo caso, se ubica en listas enlazadas asociadas a cada bloque de la tabla.

MANEJO DE DESBORDAMIENTO

Encadenamiento cerrado o interno:• La exploración puede expresarse como:

dirección = f(x) + g(x)donde:a) f(x): función de dispersión b) g(x): función de tratamiento de sobrecargas.

• Según la forma de g(x) puede hablarse de:1. Exploración lineal:

g(x) = i; 1< i < TamañoTabla

2. Exploración cuadrática:g(x) = i2; 1< i < TamañoTabla

3. Retransformación o rehashing: La función de exploración es una familia de funciones de dispersión que se examinan sucesivamente en un orden dado.

g(x) = fi(x); 1< i < m

MANEJO DE DESBORDAMIENTO

Encadenamiento cerrado o interno:• Ejemplo:

Considerando la tabla circular, la dirección vendrá dada por (f(x) + g(x)) mod TamañoTabla

a) La exploración lineal tiende a colocar las claves poco uniformemente a lo largo de la tabla, de forma que las sobrecargas van llenando bloques cercanos a los ocupados.

b) La exploración cuadrática hace examinar los bloques:f(x), (f(x)+i2) mod TamañoTabla y (f(x) – i2) mod TamañoTabla con 1≤ i ≤ (TamañoTabla - 1) / 2 Cuando TamañoTabla es un nº primo de la forma 4j + 3 con j entero, esta exploración tiende a recorrer todos los bloques de la tabla. [Radke 1970].

MANEJO DE DESBORDAMIENTO

Encadenamiento cerrado o interno:c) Retransformación: (varios tipos)Lineal:Hi(x) = (Hi-1(x) + k) mod Nk = constanteN = número de elementos de la tabla

Aleatoria:Hi(x) = (Hi-1(x) + Ai) mod NAi = nº aleatoria entre N-1 números aleatorios.

Mixtas:Hi(x) = (Hi-1(x) + F (i, x)) mod NAplican a su vez otra función de transformación que dependa de la clave. Son menos eficientes.

MANEJO DE DESBORDAMIENTO

Encadenamiento cerrado o interno:Ejercicio:Calcular las funciones de retransformación lineal para una tabla circular donde la función de dispersión inicial es el ordinal del primer carácter de las cadenas de caracteres que comienzan con ‘A’:k = 3 y N = 26

Solución:H0 = Hash (primer carácter)H0 = 1H1(x) = (H0(x) +3) mod 26H1 (A) = (1 + 3) mod 26 = 4H2 (A) = (4 + 3) mod 26 = 7

MANEJO DE DESBORDAMIENTO

• Tanto la exploración lineal, como la cuadrática o el rehashing requieren comprobaciones sucesivas con los elementos de la tabla hash.

• Muchas de ellas pueden evitarse utilizando otras estrategias de tratamiento de colisiones.

• La más elemental consiste en mantener una lista asociada a cada bloque de la tabla hash, para almacenar todos los sinónimos que no pueden insertarse en el bloque correspondiente.

• La implementación más adecuada es una lista enlazada ya que el número de sobrecargas es desconocido a priori.

• Ésta es la estrategia del encadenamiento abierto o externo que requiere disponer en cada bloque de espacio para almacenar un enlace.

MANEJO DE DESBORDAMIENTO

Encadenamiento abierto o externo:

constnpares = ...; vacia =...;

typecadena = ...; tatributo =...;posicion = 1..npares;enlace = ^par;par = record

clave: cadena;atributo: tatributo;sig: enlace;

end;Tabla = array [posicion] of par;

IMPLEMENTACIÓN

procedure Inicializar (var T: Tabla);var pos: posicion;beginfor pos := 1 to npares dobegin

T [pos].clave := vacia;T [pos].sig := nil

endend;

IMPLEMENTACIÓN

procedure Buscar (T: Tabla; c: cadena; var atrib: tatributo; var error: boolean);var pos: poscicion; p: enlace;beginpos := Hash (c);if T [pos].clave = c then{está en 1º registrobegin bloque}atrib := T [pos].atributo;error := false

endelsebeginp := T[pos].sig;error := true;while (p <>nil) and error do{recorr bloque}

if p^.clave = c then error := falseelse p := p^.sig;

if not error then atrib := p^.atributoend;

end;

procedure Insertar (var T: Tabla; c: cadena; atrib: tatributo; var error: boolean);

var pos: posicion; p: enlace;procedure Ins (var p: enlace; c: cadena; atrib: tatributo;

var error: boolean); begin {Inserta nuevo nodo en lista de desbordamiento}if p = nil then

beginerror := false;new (p); p^.clave := c; P^.atributo := atrib;P^.sig := nil;

endelse if (p^.clave = c) then error := true

else Ins (p^.sig, c, atributo, error);end;

begin {Programa principal}pos := Hash (c);if T [pos].clave = c then error := true {ya está en bloque}else if T [pos].clave = vacia then {si bloque vacío}

beginerror := false;T [pos].clave := c;T [pos].atributo := atrib

end;else Ins (T[pos].sig, c, atrib, error); {recorro el

end; bloque}

IMPLEMENTACIÓN

IMPLEMENTACIÓNprocedure Eliminar (var T: Tabla; c: cadena; var

error: boolean);var pos: posicion;procedure Sup (var p: enclace; c: cadena; var

error: boolean);var q: enlace;beginif p = nil then error := trueelse if p^.clave = c then

beginq := p; p:= p^.sig; dispose (q); error := false;

endelse Sup (p^.sig, c, error)

end;begin {Programa principal}pos := Hash (c);if T [pos].clave = vacia then error := trueelse if T [pos].clave = c then {si hay colisión}

beginerror := false; (sigue)...

IMPLEMENTACIÓNif T[pos].sig = nil then T [pos].clave = vaciaelse {si está al principio y no hay más}begin {si está al principio del bloque}p := T[pos].sig;T [pos].clave := p^.clave;T [pos].atributo := p^.atributo;T [pos].sig := p^.sig;dispose (p);

endend {del 2º if}

else Sup (T [pos].sig, c, error); {sigue por la lista

end; enlazada a ese bloque}

ANÁLISIS DE TABLAS HASH

• El factor de carga de la tabla es m/N, donde m es el número de índices distintos que se han almacenado en la tabla y N es el tamaño de la matriz que se emplea para implementarla.

• Si suponemos que todos los índices, todos los punteros y todos los valores almacenados en la tabla ocupan una cantidad de espacio constante, entonces la tabla ocupa un espacioque está en O (N + m) y la longitud mediade la lista es igual al factor de carga. Así un incremento de N reduce la longitud pero incrementa el espacio.

• Si se mantiene el factor de carga entre ½ y 1, la tabla ocupa un espacio que está en O (m), lo cual es óptimo salvo un pequeño factor cte, y la longitud media de la lista es menor que 1, lo cual implica un acceso eficiente a la tabla.

ANÁLISIS DE TABLAS HASH

• Resulta tentador mejorar este esquema sustituyendo las N listas de colisión por árboles equilibrados, pero no merece la pena si el factor de carga se mantiene en valores pequeños.

• El factor de carga se mantiene en valores pequeños mediante una redispersión. Cuando el factor de carga supera el valor uno, se dobla el tamaño de la matriz empleada para implementar la tabla de dispersión.

• La función de dispersión cambia para doblar su alcance, y todas las entradas que están en la tabla se redistribuyen a sus nuevas posiciones en alguna lista de la matriz mayor. La redistribución es costosa pero infrecuente así, no incrementa mucho el tiempo de acceso a la tabla. Cada vez que el factor de carga sobrepasa el valor uno, se reorganiza la tabla y el factor de carga vuelve a valer ½.