Está en la página 1de 13

Implementación

en Java

Taller de
Algoritmos y
Estructuras de
Datos II

1
Implementaciones
Utilizando todos los conceptos analizados en las secciones anteriores,
realizaremos nuestra implementación de tablas de hashing en Java.

Para la implementación de tablas de hash, definiremos interfaces y


utilizaremos el concepto de herencia definiendo una clase abstracta, que
será la principal clase para la implementación de las tablas de hash. Luego
extenderemos dicha clase, dependiendo de la técnica de resolución de
conflictos escogida. En este caso realizaremos la implementación
codificando un método de resolución de conflictos mediante exploración
cuadrática.

Clases e interfaces

Para la implementación de esta estructura de datos, crearemos:

 Interfaz TablaHash: va a establecer los métodos que deben definirse en


las implementaciones de las tablas de hash que va a implementar dicha
interfaz.

 Clase abstracta ExploracionTablaHash: esta clase contiene la tabla en sí


y la implementación de las operaciones. Va a implementar la interfaz
TablaHash. En esta clase definiremos como método abstracto el asociado
a la técnica de resolución de conflictos. Es decir, la clase no conoce cómo
se resuelven los conflictos.

 Clase TablaExploracionCuadratica: esta clase extiende la clase abstracta


ExploracionTablaHash definiendo el método para resolución de
colisiones de acuerdo con la resolución mediante exploración cuadrática.

 Clase TablaExploracionLinear: esta clase extiende la clase abstracta


ExploracionTablaHash definiendo el método para resolución de
colisiones de acuerdo con la resolución mediante exploración lineal.

 Interfaz Hashable: nos va a definir los métodos que deben


implementarse para cada elemento que vamos a guardar en la tabla de
hash.

 Clase EntradaHash: define una clase donde se guardará el elemento de


tipo Hashable y un atributo que indica si se encuentra borrado (dado que
vamos a realizar un borrado lógico de los datos de la tabla).

2
En la siguiente figura, se muestran las clases, interfaces y sus relaciones
mediante un diagrama de clases.

Figura 1:

Representación
Para simplificar su
complejidad, no
vamos a incluir la Para la representación de la tabla, guardaremos 2 variables en la clase
función de re- ExploracionTablaHash:
hashing. En caso
de que se quiera  Utilizaremos un vector donde guardaremos cada uno de los elementos.
implementar, Estos elementos serán del tipo Hashable.
deberíamos definir  Una variable entera (int) donde almacenaremos la cantidad de elementos
en esta clase la guardados en la tabla.
variable factor de
carga involucrada Interfaces
en el proceso de
re-hash. Primero vamos a crear la interfaz TablaHash, dentro de la cual definiremos
4 métodos:
 Void insertar(x): inserta un elemento x en la tabla de hash.
 Void remover(x): remueve un elemento x de la tabla de hash.
 Hashable buscar(x): retorna el elemento que coincide con x.
 Void vaciar(): remueve todos los elementos de la tabla.

3
Algunas aclaraciones para su implementación:

 Para las operaciones de búsqueda y remoción, si el elemento no se


encuentra, se mostrará el mensaje “Elemento no encontrado”.
 La operación de inserción sobrescribe el elemento si ya se encuentra en
la tabla.

De acuerdo con la definición descripta anteriormente, la implementación de


la interfaz TablaHash se muestra a continuación:

Figura 2:

Fuente: Libro “Estructura de Datos en Java” - Mark Weiss, Addison Wesley

Luego crearemos la interfaz Hashable. Esta interfaz solo va a definir el


método hash que va a ser calculado de acuerdo con el tamaño de la tabla.

4
Todos los objetos que se quieran guardar en la tabla de hash deberían
implementar la interfaz Hashable y redefinir el método hash (). En la
siguiente figura, se muestra el código para la interfaz Hashable.

Figura 3:

Fuente: Libro “Estructura de Datos en Java” - Mark Weiss, Addison Wesley

Clase abstracta ExploracionTablaHash

Ahora ya estamos en condiciones de crear la clase abstracta


ExploracionTablaHash. Es una clase abstracta que debe ser extendida para
implementar un algoritmo de exploración concreto como, por ejemplo,
exploración cuadrática.

El objetivo de esta clase es guardar las variables y definir los métodos


necesarios para la operación de la tabla. La tabla de datos será
implementada con un vector para permitirnos tener un acceso directo a los
datos, pero también guardaremos la cantidad de elementos almacenados en
la estructura que será implementada con una variable entera. Finalmente,
dejaremos abstracto el método que busca las posiciones donde insertar,
buscar y eliminar, lo que dependerá del algoritmo seleccionado para
resolver colisiones.

En la Figura 4, se muestran las variables y constructores de la clase. Nota que


la clase implementa la interfaz TablaHash, definida en la Figura 2.

5
Figura 4:

Fuente: Libro “Ingeniería del Software” – Roger Pressman, p. 55.

Una vez construida la clase, estamos preparados para la implementación de


los métodos de inserción, eliminación y búsqueda.

Método insertar: recibe como parámetro un objeto de tipo Hashable para


ser insertado en la tabla. La responsabilidad de encontrar la posición a donde
insertar el valor se le atribuye al método buscarPos.

Figura 5:

Fuente: Libro “Estructura de Datos en Java” - Mark Weiss, Addison Wesley

6
Método eliminar: recibe como parámetro un objeto de tipo Hashable para
ser eliminado de la tabla. La responsabilidad de encontrar la posición donde
se encuentra el valor se le atribuye al método buscarPos.

Una vez que sabemos dónde buscar el valor, accedemos a la posición y


borramos lógicamente la entrada estableciendo Activo en false.

La llamada al método confirmaBuscar simplemente llama un método que


imprime por pantalla un mensaje confirmando que se va a eliminar el
elemento o que no se encontró en la tabla.

Figura 6:

Fuente: Libro “Estructura de Datos en Java” - Mark Weiss, Addison Wesley

Método buscar: recibe como parámetro una clave y retorna el elemento


correspondiente a ese valor. Como en los métodos anteriores, el método
buscarPos es el responsable de encontrar la posición donde se encuentra el
elemento para luego recuperarlo y ser el valor de retorno de este método.

Figura 7:

Fuente: Libro “Estructura de Datos en Java” - Mark Weiss, Addison Wesley

Finalmente, vamos a definir el método buscarPos. Este método va a ser


definido como abstracto dado que la posición para insertar, eliminar y
buscar un elemento dependerá de la manera en que se van a tratar las
colisiones. Declaramos el método abstracto para ser implementado más
tarde, en la clase correspondiente.

Este método recibe una clave y retorna la posición donde se encuentra el


elemento, con dicha clave guardada en la estructura de datos.

Figura 8:

7
Fuente: Libro “Estructura de Datos en Java” - Mark Weiss, Addison Wesley

Clase TablaExploracionCuadratica

En esta sección estudiaremos la implementación de la clase


TablaExploracionCuadratica, que extiende la clase abstracta
ExploracionTablaHash. Como se pude observar en la Figura 9, dependiendo
de la resolución de conflicto elegida, se creará la clase correspondiente
extendiendo de la clase ExploracionTablaHash y se redefinirá el método
buscarPos.

Figura 9:

Fuente: Jerarquía para la clase ExploracionTablaHash

8
Como vemos en la Figura 14, se define la clase TablaExploracionCuadratica
que extiende de la clase abstracta que extiende de la clase
ExploracionTablaHash. Esta clase necesita definir el método buscarPos.

En la figura podemos observar la implementación de este método. El


objetivo es encontrar la posición que corresponde para dicho elemento de
acuerdo con su función de hash. Una vez que tenemos el valor, validamos
que no se produzcan colisiones, es decir, que la posición no se encuentre
ocupada por otro elemento. Si la posición está ocupada, se buscará una
nueva posición de acuerdo con la función cuadrática. Es decir, valor de hash
+ 12; luego se prueba con valor de hash + 22, valor de hash + 32, valor de hash
+ i2, y así sucesivamente hasta encontrar una posición vacía.

La segunda sentencia del iterador while valida si el elemento ya se encuentra


en la tabla.

Figura 10:

Fuente: Libro “Estructura de Datos en Java” - Mark Weiss, Addison Wesley

Clase EntradaHash

Finalmente, vamos a revisar la clase EntradaHash. Esta clase define el


elemento que va a ser guardado en la tabla, que es de tipo Hashable, y un
booleano que establece si el elemento está activo o no, lo que nos permite
un borrado lógico de los datos.

En la siguiente figura, se muestra el código de esta clase.

9
Figura 11:

Fuente: Libro “Estructura de Datos en Java” - Mark Weiss, Addison Wesley

Interfaz Hashable

Para completar la implementación de la estructura de datos, vamos a definir


la interfaz Hashable. Esta interfaz define que debe implementarse el método
hash para cada objeto que la implemente.

En la siguiente figura, vemos el código de la interfaz.

Figura 12:

Fuente: Libro “Estructura de Datos en Java” - Mark Weiss, Addison Wesley

Una vez creada la interfaz, estamos listos para crear nuestros objetos y
almacenarlos en la tabla de hash.

10
Figura 13: Implementación de la clase Persona

Figura 14: Implementación de la clase MyInteger

Tablas de hash en el paquete Java.utils

Veamos la implementación que nos trae Java de las tablas de hash.

En el siguiente ejemplo, se muestra la utilización de las tablas de hash del


paquete java.utils.

Supongamos que tenemos una lista de clientes de un negocio con un saldo


a favor para gastar en el local. Analicemos qué pasa en cada uno de los pasos.

11
Figura 15: Código ejemplo utilizando hashtables del paquete java.utils

Línea 12: creación de la tabla de hash saldo.

Línea 13: creación de la tabla de hash saldo2. La diferencia con la línea


anterior es que la tabla se encuentra parametrizada con los tipos de datos
que vamos a guardar como Clave y Valor. En este caso la Clave será de tipo
String y el Valor de tipo Double.

Línea 19-22: inserta en la tabla de hash los valores Persona, Saldo, Clave y
Valor (método put).

Línea 26: obtiene una enumeración con todos los nombres de personal o
claves de la tabla de hash para su recorrido (método keys).

Línea 27-28: ciclo para iterar sobre el enumerado obtenido en la línea 26.

Línea 29: obtiene el valor almacenado en la tabla de acuerdo con la clave


que se pasa como parámetro; en este caso, un nombre (método get).

Línea 32: verifica si la clave se encuentra almacenada en la tabla y retorna


verdadero o falso (método containskey).

12
Referencias
Weiss, M. (2000). Capítulo 19. En Autor, Estructura de Datos en Java.
Addison Wesley Iberoamericana.

Capítulo: 11
Thomas, H., Cormen, C. E., Leiserson, R. L., & Rivest, C. S. (2001). Capítulo
11. En Autor, Introduction to Algorithms (2nd ed.): McGraw-Hill Book
Company

Capítulo: 11
Lafore, R. (2002). Capítulo 11. En Autor, Data Structures & Algorithms in Java
(2nd ed.). SAMS.

13

También podría gustarte