Sunteți pe pagina 1din 8

Qu son las tablas hash

Una tabla Hash es un contenedor asociativo (tipo Diccionario) que permite un


almacenamiento y posterior recuperacin eficientes de elementos (denominados valores) a
partir de otros objetos, llamados claves.
Tras esta explicacin preliminar vamos a entrar en detalle.
Una tabla hash se puede ver como un conjunto de entradas. Cada una de estas entradas
tiene asociada una clave nica, y por lo tanto, diferentes entradas de una misma tabla
tendrn diferentes claves. Esto implica, que una clave identifica univocamente a una
entrada en una tabla hash.
Por otro lado, las entradas de las tablas hash estn compuestas por dos componentes, la
propia clave y la informacin que se almacena en dicha entrada.

La estructura de las tablas hash es lo que les confiere su gran potencial, ya que hace de ellas
unas estructuras extremadamente eficientes a la hora de recuperar informacin almacenada.
El tiempo medio de recuperacin de informacin es constante, es decir, no depende del
tamao de la tabla ni del nmero de elementos almacenados en la misma.
Una tabla hash est formada por un array de entradas, que ser la estructura que almacene
la informacin, y por una funcin de dispersin. La funcin de dispersin permite asociar el
elemento almacenado en una entrada con la clave de dicha entrada. Por lo tanto, es un
algoritmo crtico para el buen funcionamiento de la estructura.
Cuando se trabaja con tablas hash es frecuente que se produzcan colisiones. Las colisiones
se producen cuando para dos elementos de informacin distintos, la funcin de dispersin
les asigna la misma clave. Como se puede suponer, esta solucin se debe arreglar de alguna
forma. Para ello las tablas hash cuentan con una funcin de resolucin de colisiones.
Existen dos tipos de tablas hash, en funcin de cmo resuelven las colisiones:
Encadenamiento separado: Las coliciones se resuelven insertndolas en una lista.
De esa forma tendramos como estructura un vector de listas. Al nmero medio de
claves por lista se le llama factor de carga y habra que intentar que est prximo a
1.
Direccionamiento abierto: Utilizamos un vector como representacin y cuando se
produzca una colisin la resolvemos reasignndole otro valor hash a la clave hasta
que encontremos un hueco.
Qu son las tablas hash
Una tabla Hash es un contenedor asociativo (tipo Diccionario) que permite un
almacenamiento y posterior recuperacin eficientes de elementos (denominados valores) a
partir de otros objetos, llamados claves.
Tras esta explicacin preliminar vamos a entrar en detalle.
Una tabla hash se puede ver como un conjunto de entradas. Cada una de estas entradas
tiene asociada una clave nica, y por lo tanto, diferentes entradas de una misma tabla
tendrn diferentes claves. Esto implica, que una clave identifica univocamente a una
entrada en una tabla hash.
Por otro lado, las entradas de las tablas hash estn compuestas por dos componentes, la
propia clave y la informacin que se almacena en dicha entrada.

La estructura de las tablas hash es lo que les confiere su gran potencial, ya que hace de ellas
unas estructuras extremadamente eficientes a la hora de recuperar informacin almacenada.
El tiempo medio de recuperacin de informacin es constante, es decir, no depende del
tamao de la tabla ni del nmero de elementos almacenados en la misma.
Una tabla hash est formada por un array de entradas, que ser la estructura que almacene
la informacin, y por una funcin de dispersin. La funcin de dispersin permite asociar el
elemento almacenado en una entrada con la clave de dicha entrada. Por lo tanto, es un
algoritmo crtico para el buen funcionamiento de la estructura.
Cuando se trabaja con tablas hash es frecuente que se produzcan colisiones. Las colisiones
se producen cuando para dos elementos de informacin distintos, la funcin de dispersin
les asigna la misma clave. Como se puede suponer, esta solucin se debe arreglar de alguna
forma. Para ello las tablas hash cuentan con una funcin de resolucin de colisiones.
Existen dos tipos de tablas hash, en funcin de cmo resuelven las colisiones:
Encadenamiento separado: Las colisiones se resuelven insertndolas en una lista. De esa
forma tendramos como estructura un vector de listas. Al nmero medio de claves por
lista se le llama factor de carga y habra que intentar que est prximo a 1.
Direccionamiento abierto: Utilizamos un vector como representacin y cuando se
produzca una colisin la resolvemos reasignndole otro valor hash a la clave hasta que
encontremos un hueco.
Creando y usando tablas Hash en C/C++
Las tablas hash son una implementacin eficiente de una amplia
estructura de datos con claves, una estructura a veces conocido
como una matriz asociativa o un mapa. Si ests trabajando en
C++, tu puedes tomar ventaja del STL Map Container para
matrices con claves implementadas mediante rboles binarios,
pero este artculo te dar un poco de la teora detrs de cmo
funciona una tabla hash.
Matrices con claves vs. Matrices
indexadas.

Uno de los mayores inconvenientes de un lenguaje como C es que
no hay matrices con clave. En una matriz normal de C (tambin
denominada matriz indexada), la nica manera de acceder a un
elemento sera a travs de su nmero de ndice. Para encontrar el
elemento 50 de una matriz denominada "empleados" tienes que
acceder a ella de esta manera:
empleados [50];
En una matriz con clave, sin embargo, t seras capaz de asociar
cada elemento con una "clave", que puede ser cualquier cosa,
desde un nombre a un nmero de modelo del producto. Por lo
tanto, si tienes una matriz con clave de los registros de los
empleados, se puede acceder al registro del empleado "John
Brown" de esta manera:
empleados ["Brown, John"];
Una forma bsica de matriz con claves se llama tabla hash. En
una tabla hash, una clave se utiliza para encontrar un elemento
en lugar de un nmero de ndice. Dado que la tabla hash tiene que
ser codificado utilizando una matriz indexada, tiene que haber
alguna manera de transformar una clave en un nmero de ndice.
De esta manera se llama la funcin hash.

Las funciones hash

Una funcin hash puede ser casi cualquier cosa. La manera en que
la funcin de hash es en realidad programada depende de la
situacin, pero en general la funcin hash debe devolver un valor
basado en una clave y el tamao de la matriz en la que est
construida la tabla. Adems, una cosa importante que a veces se
pasa por alto es que una funcin hash tiene que devolver el
mismo valor cada vez que se da la misma clave.

Digamos que queremos organizar una lista de cerca de 200
direcciones por los apellidos de las personas. Una tabla hash sera
ideal para este tipo de cosas, pudiendo acceder a los registros con
los apellidos como clave.


En primer lugar, tenemos que determinar el tamao de la matriz
que estamos usando. Vamos a usar una matriz de 260 elementos,
as que puede haber un promedio de 10 espacios de elementos
por letra del alfabeto.

Ahora, tenemos que hacer una funcin hash. En primer lugar,
vamos a crear una relacin entre letras y nmeros:
A -> 0
B -> 1
C -> 2
D -> 3
...y as sucesivamente hasta Z -> 25.
La forma ms sencilla de organizar la tabla hash se basa en la
primera letra del apellido.

Ya que tenemos 260 elementos, podemos multiplicar la primera
letra del apellido por 10. Por lo tanto, cuando una clave como
"Smith" es recibida, la clave se transforma en el ndice de 180 (S
es la letra 19 del alfabeto, por lo que S -> 18, y 18 * 10 = 180).

Dado que se utiliza una funcin simple para generar un nmero de
ndice rpidamente, y se utiliza el hecho de que el nmero de
ndice se puede utilizar para acceder a un elemento directamente,
el tiempo de acceso a la tabla de hash es bastante pequeo. Una
lista enlazada de claves y elementos no sera tan rpido, ya que
tendra que buscar a travs de todos y cada uno de los elementos
clave par.

Las colisiones y manejo de colisiones.

Los problemas, por supuesto, surgen cuando tenemos apellidos
con la misma letra. As "Webster" y el "Whitney" se correspondera
con el mismo nmero de ndice, 22. Una situacin como esta
cuando dos claves son enviadas a la misma ubicacin en la matriz
se llama una colisin. Si ests tratando de insertar un elemento,
puedes encontrarte con que el espacio ya est ocupado por otro.

Por supuesto, podrsa tratar de hacer slo una enorme variedad y
por lo tanto hacer que sea casi imposible que una colisin suceda,
pero que contradice el objetivo de utilizar una tabla hash. Una de
las ventajas de la tabla hash es que es a la vez rpido y pequeo.

Manejo de colisiones con
direccionamiento abierto

El algoritmo manipulacin de colisiones ms simple se conoce
como el mtodo de direccin abierta o el mtodo de dispersin
cerrada. Cuando se agrega un elemento, por ejemplo "Whitney",
y te encuentras con que otro elemento ya est ah ("Webster",
por ejemplo), entonces pasas al siguiente elemento del espacio (el
que est despus de "Webster"). Si esto se llena, te vas a la
siguiente, y as sucesivamente, hasta que encuentre un espacio
vaco para insertar el nuevo elemento (todos los elementos
adicionales vinieron muy bien despus de todo!)
...
220 "Blanco" | <- # # # # # # COLISSION: seguir
adelante a la siguiente.
221 "Webster" | <- # # # # # # COLISSION:
Siguiente.
222 | Ahhh, perfecto. Inserte aqu.
223 |
...
Ya que se modificamos el algoritmo de insercin, tambin tenemos
que cambiar la funcin en la que se encuentra el elemento. Tienes
que tener alguna manera de verificar que has encontrado el
elemento que deseas, y no algn otro elemento. La forma ms
sencilla es comparar simplemente las claves (Tiene este registro
el apellido "Whitney"? Es ste?). Si el elemento que encontramos
no es uno de ellos, simplemente pasa al siguiente elemento hasta
llegar al que quieres o te encuentras con un espacio vaco (que
significa que el elemento no est en la tabla).

Suena simple, verdad? Bueno, la cosa se complica. Qu pasa si
tienes tantas colisiones que te desbordas fuera de la matriz?

Si estas tratando de insertar "Zorba" y todos los elementos estn
llenos debido a la manipulacin de la colisin, entonces qu? Mira
el ejemplo:
...258 "Whitney" | <- No, no es vaco
259 "Zenn" | No, no est vaco
---------------- <- Ummm, y ahora qu?
Lo ms fcil que se puede hacer es ajustar de nuevo el principio.
Si todava no hay espacios vacos, entonces tenemos que cambiar
el tamao de la matriz, ya que no hay suficiente espacio en la
tabla hash para todos los elementos. Si cambiamps el tamao de
la matriz, por supuesto, vamos a tener que inventarnos una vuelta
de tuerca para nuestra funcin hash (o al menos cmo lo
manejamos), de modo que cubra el rango correcto de los valores
de nuevo, pero al menos tendremos espacio. (Ten en cuenta que
cambiar el tamao de la matriz significa que de vez en cuando se
inserta un valor en la lista provocar una operacin de copia
suceda (O (n)) pero que en promedio esto ocurre slo una vez
para cada n elementos insertados, por lo que la insercin debera
estar en un promedio constante de tiempo, O (1). Si no ests
seguro de lo que trminos como "O (n") y "Constante de tiempo"
quiere decir, echa un vistazo a la serie de artculos
Cprogramming.com en la eficiencia de algoritmos (estan en
ingls). Como puedes ver, el cambio de tamao no es tan malo -
aun as, si sabes la cantidad de espacio que se necesita para
empezar, puedes ahorrarte un poco de trabajo.

Manejo de las colisiones con
encadenamiento separado

Una segunda estrategia de manipulacin de colisiones es la de
almacenar una lista enlazada en cada elemento de la estructura de
datos hash. De esta manera, cuando se produce una colisin,
puedes agregar el elemento en la lista enlazada que se almacena
en el ndice hash. Si tienes un solo elemento con un valor hash en
particular, entonces tienes un elemento de lista - sin penalizar el
rendimiento. Si tienes un montn de elementos devolviendo un
hash al mismo valor, vers una desaceleracin, por supuesto, pero
no ms que de lo que veras con colisiones de hash.

Una cosa buena del encadenamiento separado es que tener un
montn de valores que devuelven un hash cerca uno del otro es
menos importante. Con el direccionamiento abierto, si tienes un
conjunto de valores que hacen hash para casi el mismo valor, te
quedars sin espacio abierto en esa parte de la matriz. Con
encadenamiento separado, cada elemento que tiene un valor hash
diferente no tendr impacto en los dems elementos.

Cambio dinmico de tamao basado en
factor de carga

En general, no quieres que tu tabla hash crezca hasta quedar
completamente llena, ya que esto har que las bsquedas
necesiten mucho ms tiempo. Si un valor no est en la matriz, con
direccionamiento abierto, tienes que seguir buscando hasta que
llegues a un lugar vaco o que vuelva al punto de partida - en
otras palabras, con una tabla completamente llena, las bsquedas
pueden ser O (n), que es horrible. Una implementacin real de la
tabla hash har un seguimiento de su factor de carga, la relacin
de los elementos en cuanto al tamao de la matriz. Si tienes una
matriz de 10 elementos, con 7 elementos, el factor de carga es de
0,7. De hecho, 0,7 por lo general es el momento adecuado para
cambiar el tamao de la matriz subyacente.

La eleccin de un buen algoritmo de
hash

Cuanto ms colisiones haya, peor ser el rendimiento de tu tabla
hash. Con suficientes elementos de la tabla hash, se puede
obtener un rendimiento medio que es bastante bueno - tiempo
esencial constante O (1). El truco es hacer que la matriz crezca
con el tiempo a medida que se empieza a llenar la matriz. Pero si
tienes un montn de elementos que devuelven hash al mismo
valor, entonces tendrs que empezar a hacer una bsqueda a
travs de una lista de elementos en la que todos tengan el mismo
valor hash. Esto puede hacer que las bsquedas de hash pasen de
ser de tiempo constante a ser, bueno, de tiempo lineal en el
nmero de elementos. Imagina que tu funcin hace hash de todos
los valores a 0, poniendolos en el primer elemento de la matriz.
En ese caso sera slo una forma muy complicada de implementar
una bsqueda lineal.

La eleccin de un algoritmo de hash bien puede requerir algn tipo
de atencin y la experimentacin, y depender de tu dominio del
problema. Si ests trabajando con los nombres, es probable que
no quieras un algoritmo de hash que slo se fije en la primera
letra, ya que las letras del alfabeto no se utilizan de manera
uniforme - encontrars muchos ms nombres comienzan con S o
con Z. Tambin querrs que tus funciones hash sean rpidas - no
deseas perder todos el tiempo que vienes ahorrando en tu tabla
hash porque est calculando la funcin de hash muy lentamente.
Es un equilibrio delicado. Aqu hay un buen ejemplo de una
funcin hash, de la mano de azillionmonkeys.com. La explicacin
est en ingls pero la intencin en entender el cdigo.

Ahora ests listo para implementar tu primera tabla hash! Dale
una oportunidad. No es demasiado difcil, y el resultado final es
bastante til.

Va|www.cprogramming.com

S-ar putea să vă placă și