Está en la página 1de 16

Materia: Algoritmos y Programación II

HASHING

Emiliano Castagnari 82930


Andrés de Barbará 82497
Sebastián Santisi 82069

2.do cuatrimestre 2003


ÍNDICE

Índice
1. Hashing 2
1.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2. Resolviendo colisiones de hasheo por direccionamiento abierto . . . 3
1.3. Borrando elementos desde una tabla de hasheo . . . . . . . . . . . . 6
1.4. Tablas de hasheo encadenadas . . . . . . . . . . . . . . . . . . . . . 6
1.5. Eficiencia en los métodos de rehasheo . . . . . . . . . . . . . . . . . 7
1.6. Reordenamiento de la tabla de hasheo . . . . . . . . . . . . . . . . 9
1.7. Método de Brent . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.8. Árboles binarios de hasheo . . . . . . . . . . . . . . . . . . . . . . . 10

2. El Contenedor Asociativo de Hasheo de la Bibloteca Estandar de


Plantillas (STL) 12
2.1. Tipos nuevos del Contenedor . . . . . . . . . . . . . . . . . . . . . . 12
2.2. Notación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3. Definiciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.4. Funciones del Contenedor : . . . . . . . . . . . . . . . . . . . . . . . 13
2.5. Garantias de complejidad . . . . . . . . . . . . . . . . . . . . . . . . 13
2.6. Modelos en el contenedor : . . . . . . . . . . . . . . . . . . . . . . . 14

3. Bibliografı́a 14

1
1 Hashing

1. Hashing
Hash, x. There is no definition for this word - nobody knows what hash is”
AMBROSE BIERCE (The Devil’s Dictionaty, 1906)

1.1. Introducción
Supongamos que tenemos un registro que se encuentra guardado en una tabla
con una correspondiente clave. Es necesario para operar sobre ese dato, tener que
analizar cierto número de estos registros antes de obtener el que estamos buscan-
do. Para mejorar nuestro rendimiento y llevarlo a un nivel óptimo nos convendrı́a
analizar que distribución en la tabla y que método de búsqueda podrı́amos usar
para no realizar comparaciones innecesarias.

Si queremos que cada clave sea devuelta en un solo acceso, entonces el lugar
de cada registro en la tabla solo puede depender de una sola clave y no depender
de la localización de las otras claves como ocurre en un árbol. El método mas
eficiente de organizar tal tabla, es un arreglo donde cada registro es almacenado a
una distancia especifica desde la base de este.

Por desgracia un sistema como el descrito anteriormente no es muy práctico.


Por ejemplo, pensemos en una compañı́a que tiene que administrar un stock de
100 objetos diferentes, los cuales poseen un número de serie de siete(7) dı́gitos. Si
usáramos indexación directa necesitarı́amos un arreglo de 10 millones de elementos
y esto es claramente una pérdida inaceptable de espacio.

Lo que necesitamos es un método que nos permita convertir una clave de un


elemento en un entero que represente la distancia a la base del arreglo donde se
encuentra el registro, y que, idealmente, no hallan dos claves que tengan el mismo
registro final.
Desafortunadamente no existe tal método, pero intentemos entonces encontrar uno
que se le acerque lo suficiente al ideal y determinemos qué tipo de acción tomar
cuando no se aproxima a este.

A la función que transforma un clave en un ı́ndice de una tabla se le llama


función de hasheo (hash function). Si h es una función de hasheo y clave es una
clave entonces h(clave) es el hasheo de la clave. Si r es el registro cuya clave hashea
en hr, entonces hr es la clave de hasheo de r.

Supongamos ahora que una empresa que tiene 1000 partes diferentes en su
stock y cada parte tiene un registro diferente. Entonces un arreglo indexado del 0
al 1000 es suficiente para poder guardar todo el archivo de stock. Los últimos tres

2
1.2 Resolviendo colisiones de hasheo por direccionamiento abierto

números del número de registro de las partes nos va a servir como ı́ndice de los los
registros en el arreglo.

El método anterior tiene una falla. Supongamos que dos claves, c1 y c2, son
aquellas tal que h(c1) y h(c2) son iguales. Claramente si c1 esta en la tabla, cuan-
do se queramos incluir c2 se intentara acceder al el registro donde se encuentra c1.
Dos registros no pueden ocupar la misma posición. Cuando esto ocurre se llama
colisión de hasheo (hash collision) o hash clash.

Hay dos formas básicas de resolver esto. La primera es llamada rehasheo (re-
hashing), que incluye usar una función de hasheo secundaria en la clave de hasheo
del registro. La segunda, llamada encadenamiento (chaining), construye una lista
enlazada de todos los elementos cuyas claves hashean en el mismo ı́ndice.

Mas allá de esto, cabe decir que una buena función de hasheo es aquella que
minimizan las colisiones y distribuye de forma uniforme los registros. Dejar es-
pacios en blanco en un arreglo es ineficiente en termino de espacio, pero reduce
sensiblemente la necesidad de resolver los hash clashes y, por lo tanto, gana en ve-
locidad. Más adelante mostraremos las diferencias de rendimiento entre una tabla
medianamente llena y una tabla llena; este es un tema no menor que requiere bas-
tante análisis.

Vale también destacar que el hecho de que hashing permita el acceso directo a
los elementos de la tabla posee una falla muy seria. Los elementos de la tabla de
hasheo no son guardados en forma secuencial por claves y no hay métodos prácti-
cos para obtener las claves en alguna secuencia dada.

1.2. Resolviendo colisiones de hasheo por direccionamien-


to abierto
Un método simple para resolver colisiones de hasheo es el de poner el registro
en la siguiente posición disponible en el arreglo. Esta técnica es llamada compro-
bación lineal(lineal probing) y es un ejemplo de un método general para resolver
colisiones de hasheo llamado rehasheo (rehashing) o direccionamiento abierto (open
addresing). En general una función de rehasheo, rh, acepta un ı́ndice del arreglo
para calcular otro. Si la posición h(clave) del arreglo ya se encuentra ocupada por
un registro con una clave diferente, rh es aplicada al valor de h(clave)para encon-
trar otra posición donde el registro pueda ser guardado. Si esta última posición se
encuentra también ocupada puede ser aplicada la función, nuevamente, para saber
sı́ rh(rh(h(clave))) esta disponible.

3
1.2 Resolviendo colisiones de hasheo por direccionamiento abierto

Notemos que puede ocurrir que en el rehasheo nunca se encuentre una posición
disponible por lo que se seguirı́a intentando calcular sin ningún resultado infini-
tamente. Esto puede pasar por dos motivos. Primero que la tabla este completa,
lo cual es fácilmente salvable contando las veces que se aplica la función y com-
parando contra el total de elementos de la tabla. Segundo existen posiciones libres
en la tabla pero la función de rehasheo nunca las toca. Consideremos la situación
donde las los impares están llenos, los pares vacı́os, y la función de rehasheo solo
toca los impares.

Una de las propiedades de la una buena función de rehasheo es aquella que


para cualquier ı́ndice i, los sucesivos rehasheos rh(i),rh(rh(i)),etc, cubre enteros
desde 0 hasta el tamaño de la tamtabla - 1.

Existe otra forma de medir la eficiencia de la función de rehasheo. Considere-


mos el caso de un rehasheo lineal. Considerando que la función de hasheo produce
ı́ndices de que son uniformemente distribuidos sobre intervalos de 0 y tamtabla -
1. Cuando el arreglo está vacı́o veremos que cualquier registro será ingresado en
la tabla. Luego, que se hayan realizado varias entradas y algunas colisiones hayan
sido resueltas, lo anterior ya no será cierto. El efecto en el cual dos claves que
hashean en diferentes valores compiten entre ellas en sucesivos rehasheos se llama
agrupamiento primario (primary clustering).

De hecho las funciones que dependen exclusivamente de los ı́ndices ha ser re-
hasheados causan agrupamiento primario.

4
1.2 Resolviendo colisiones de hasheo por direccionamiento abierto

Una forma de resolver este problema es permitir que la función de rehasheo


dependa del número de veces que la función fue aplicada a un valor particular de
hasheo. De esta forma rh es una función de dos argumentos. rh(i,j) depende del
entero de rehasheo i y de la clave que esta siendo rehasheada por j -esima ves.

Otro método para solucionar este problema es usar permutación aleatoria de


los números entre 1 y t ( donde t es igual a tamtabla -1 ), y dejar el j -esimo re-
hasheo de h(clave) ser (h(clave) + pj) % tamtabla.

Un tercer método para eliminar el (primary clustering) (agrupamiento pri-


mario) es el de hacer que la función j -esima de rehasheo sea (h(clave) + 2 ) %
tamtabla. Este método es llamado rehasheo cuadrático (quadratic rehash)... el cual
cabe decir que si bien reduce bastante el riesgo de clustering tiene la desventaja de
que en el mejor de los casos sólo cubre la mitad de las claves de la tabla y puede
pasar de no poderse ingresar elementos nuevos cuando todavı́a queda espacio libre.

Mientras que estos métodos eliminan agrupamiento primario no eliminan otro


fenómeno llamado agrupamiento secundario (secundary clustering), en el cual
diferentes claves que hashean al mismo valor sigue el mismo camino de rehasheo.

Una forma de eliminar cualquier clase de agrupamiento es usar doble hasheo


(double hashing), el cual involucra el uso de dos funciones de hasheo, h1(clave) y
h2(clave). h1, la cual es conocida por función primaria de hasheo (primary hash
function), es usada primero usada para determinar la posición en la cual el registro
debe ser guardado. Si esa posición esta ocupada, la función de rehasheo rh(i,clave)
= (i + h2(clave)) % tamtabla es usada sucesivamente hasta que se encuentre un
elemento de la tabla vacı́o. Mientras h2(clave1) no iguale h2(clave2), registros con
claves clave1 y clave2 no competirán por el mismo lugar.

5
1.3 Borrando elementos desde una tabla de hasheo

1.3. Borrando elementos desde una tabla de hasheo


Es muy dificultoso borrar elementos de una tabla de hasheo que usa rehasheo
para búsquedas e inserciones. Supongamos que el registro r1 está en la posición
p. Para sumar un registro r2 cuya clave hashea en p, este debe ser insertado en la
primera posición libre que se encuentra tras volver aplicar la función de hasheo en
el ı́ndice obtenido, es decir, en la posición rh(p), rh(rh(p)), etc. Supongamos que
r1 es borrado, entonces esa posición esta ahora vacı́a. Ahora si buscamos por r2,
vamos a hacer rh(p), donde estaba r1, y la encuentra vacı́a por lo tanto piensa que
r2 no esta en la tabla.

Una solución posible a este problema es que marquemos a este registro como
borrado y no como vacı́o. Entonces la búsqueda solo se detendrá si encuentra un
registro vacı́o y no uno borrado. Pero esta solución solo será viable si nos encon-
tramos con pocos registros borrados, ya que si este no fuera el caso, las búsquedas
tocarı́an muchas posiciones marcadas como borradas antes de concluir.

1.4. Tablas de hasheo encadenadas


Hasta el momento hemos planteado varias de las desventajas que conllevan las
tablas de dirección abierta, muchas de estas desventajas no existen en las tablas
de hasheo encadenadas.

Como ya se dijo, el procedimiento consiste en hacer un ı́ndice general que se


corresponda con los posibles valores de h(c1), este ı́ndice apunta a listas enlazadas.
Luego, no existen colisiones dado que si dos claves hashean en el mismo ı́ndice,
simplemente se añade una cadena (chain) a la lista.

Tampoco existe el problema de la eliminación de claves, dado que solamente


basta con eliminar el nodo correspondiente en la lista.

La desventaja de este método con respecto al método de open adressing es que


si demasiadas claves hashean en el mismo ı́ndice, las listas crecen considerable-
mente, convirtiendo el problema en una búsqueda lineal; y el otro inconveniente
de este método, es que el acceso a un array es mucho más rápido que el acceso a
una lista.

6
1.5 Eficiencia en los métodos de rehasheo

1.5. Eficiencia en los métodos de rehasheo


Utilizando rehasheo, el promedio de comprobaciones depende en la función de
hasheo y el método de rehasheo. Asumamos que todas las funciones de hasheo son
uniformes. Si n es el número de elementos y tamtabla es el tamaño de la tabla.
Si tamtabla es grande queda demostrado que en una obtención exitosa usando re-
hasheo lineal es aproximadamente:

2∗tamtabla
2∗tamtabla−n+2

Definiendo factor de carga, fc como n/tamtabla. Cuandopel factor de carga se


aproxima a 1 esta formula es inútil y en cambio debemos usar 2 (pi ∗ tamtabla/8)+
0, 33.

Para una búsqueda no exitosa 0,5 / (1 - fc) 2 + 0,5 para tamaños de tablas
grandes. Cuando la tabla esta llena el número máximo de comprobaciones a re-
alizar es (tamtabla + 1) / 2.

Para tablas pequeñas el número es razonable pero para tablas grandes este
puede mejorarse eliminando el agrupamiento primario seteando rh(i,clave) a rh(i
+ hkey) % tamtabla como definimos antes o usando rehasheo cuadrático. Esto
deja el número de comparaciones en aproximadamente 1 - log (1 - fc) - fc/2
para búsquedas no exitosas. Para tablas completas las búsquedas exitosas son en
(tamtabla + 1) y las no exitosas se mantienen en orden (tamtabla + 1) / 2.

El doble hasheo mejora la eficiencia eliminando el agrupamiento primario y


el secundario. El hasheo uniforme es definido como cualquier esquema de hasheo
en el cual cualquier elemento nuevo insertado tiene las mismas posibilidades de
ser insertado en cualquiera de las posiciones libres de la tabla. Para este esquema
teórico, puede ser probado que el tiempo de una búsqueda exitosa es aproximada-
mente log (1 - fc) / fc; y que una no exitosa requiere (tamtabla + 1) / (tamtabla +
1 - n) o aproximadamente 1 / (1 - fc) para tablas grandes. Para tablas completas
el tiempo de búsqueda exitosas es de log * (tamtabla + 1) - 0,5 y para no exitosas
(tamtabla + 1) / 2.

7
1.5 Eficiencia en los métodos de rehasheo

Estos datos indican que el hasheo lineal debe ser evitado para tablas que están
a más del 75 % de su capacidad, especialmente si las búsquedas son frecuentes,
ya que el agrupamiento primario tiene un significativo impacto en los tiempos
de búsquedas. En cambio el agrupamiento secundario sólo adiciona un 0,5 com-
probaciones al número promedio requerido. Dado el hecho de que el doble hasheo
requiere cálculos adicionales para determinar h2(clave), tal vez sea preferible acep-
tar la media comprobaciones extra y usar rh(i,clave) = (i + hclave) % tamtabla.

Otra técnica que puede mejorar el método de rehasheo lineal es rehasheo lin-
eal de secuencias divididas. Este método se basa en que cuando encontramos que
h(clave) está ocupado, comparamos clave con la clave de kh encontrada en la
posición h(clave). Si kh < h(clave), usamos la función de rehasheo i + c1 ; si
kh > h(clave), usamos i + c2, como función de rehasheo. Esta técnica reduce
el número de comprobaciones en búsquedas exitosas en más de un 50 % y en
búsquedas no exitosas en mas de 80 %. De cualquier forma las formas de rehasheo
no lineales son todavı́a mejores. Las tablas anteriores también demuestran que el
gran gasto que conlleva tener tablas casi llenas para una búsqueda no exitosa.
Las inserciones también requieren el mismo número de comparaciones que las
búsquedas no exitosas. Cuando la tabla esta casi llena las inserciones se aproxi-
man a una búsqueda secuencial y es peor que una la inserción en un árbol.

8
1.6 Reordenamiento de la tabla de hasheo

Respecto de las tablas resueltas mediante chaining hay que decir que hay un
detalle importante para comenzar; en las tablas de direccionamiento, fc es siempre
menor a uno, dado que surge de la división del número de claves por el tamaño de
la tabla. En el método de encadenamiento fc puede ser mayor que uno dado que
no existen restricciones al número de claves a almacenar.

Los tiempos promedios de búsqueda en tablas encadenadas son del orden de 1


+ fc/2 para búsquedas exitosas y fc para búsquedas fallidas.

Es evidente que las tablas encadenadas tienen buen rendimiento aún cuando el
factor de carga es grande, cosa que no ocurre en las tablas de hashing de dirección
abierta.

Hay que decir algo muy importante acerca de la técnica de hashing, y esto es
que en ningún momento el tiempo de búsqueda depende de la cantidad de claves
sino que depende exclusivamente del fc; es decir, por más que en una tabla hayan
millones de entradas, si el tamaño de la tabla es suficientemente grande y la función
de hasheo es la adecuada, el tiempo de búsqueda estará siempre acotado y será el
mismo que para una tabla con sólo 10 entradas y con un tamaño proporcional al
anterior. Esto quiere decir que una tabla de hasheo permite realizar de búsquedas
en un orden O(1) dado que no depende del tamaño de la entrada.

1.6. Reordenamiento de la tabla de hasheo


Cuando la tabla esta casi completa, muchos de los elementos de la tabla no
están en los lugares dados por sus claves de hasheo. Deben hacerse muchas com-
paraciones antes que de encontrar alguno de los elementos. Si el elemento no esta
en la tabla, entonces la totalidad de las posiciones de rehasheo deben ser exam-
inadas antes de que esta se determine. Existen varias técnicas por las cuales se
puede remendar esta situación.

El primer método descubierto por Amble y Knuth, dice que una serie de ele-
mentos que hashean en un mismo elemento se mantienen en orden descendiente
de claves. Cuando buscamos por un elemento no es necesario rehashear repetida-
mente hasta obtener un elemento vacı́o sino que en cuanto obtenemos un elemento
cuya clave es menor a la clave de búsqueda entonces sabemos que el elemento no
se encuentra en la tabla de hasheo. Cuando insertamos un elemento en la tabla, si
accedemos a una clave que es menor a nuestra clave, entonces remplazamos nuestra
clave, la clave a insertar, por la menor, que se encuentra en la tabla, y continuamos
el proceso de inserción con la clave menor. Una tabla ordenada de esta forma se

9
1.7 Método de Brent

llama tabla ordenada de hasheo (ordered hash table).

Usar una tabla ordenada de hasheo no cambia el número promedio de com-


paraciones necesarias para encontrar una clave que esta en una tabla, pero reduce
significativamente el número de comparaciones para determinar que una clave no
existe en una tabla. Puede demostrarse que el número total de comparaciones nece-
sarias para una búsqueda exitosa y una no exitosa es la misma. Desgraciadamente
el promedio de comparaciones requeridas para una inserción no se ve reducido
en una tabla ordenada de hasheo e iguala el número requerido por una búsqueda
no exitosa en una tabla no ordenada. Las inserciones en una tabla ordenada tam-
bién requieren de una significante cantidad de modificaciones en la tabla de hasheo.

1.7. Método de Brent


Richard P. Brent descubrió que el tiempo promedio de las búsquedas exitosas
podı́a ser contenido a medida que una tabla se fuera llenando. La técnica de Brent
esta basada en el echo de que una búsqueda exitosa es mucho más común que una
inserción, por lo tanto, realizando un poco mas de trabajo en la inserción, ganamos
tiempo en las búsquedas, dado una gran ventaja de rendimiento final. El méto-
do requiere rehasheo de los argumentos de búsqueda hasta que un espacio vacı́o
es encontrado. Cada clave en el camino de rehasheo es a su ves rehasheada para
determinar si ubicar alguna de ellas en un espacio vacı́o requerirá mas rehasheos.
Si este es el caso, los argumentos de búsqueda remplazan la siguiente clave en la
tabla y la clave existente es insertada en su espacio de rehasheo.

1.8. Árboles binarios de hasheo


Otro método para mejorar el algoritmo de Brent es atribuido a Gonnet y a
Munro y es llamado Árbol Binario de Hasheo.
Cada nodo del árbol contiene un ı́ndice en la tabla de hasheo. Entonces el nodo
raı́z del árbol será nodo(0),nodo(2 * i + 1) y nodo(2 * i + 2) serán su hijo dere-
cho e izquierdo respectivamente. Los ı́ndices de la tabla de hasheo contenido en
nodo(i) serán referenciados como ı́ndice(i), y su clave en esa posición como clave(i).

Para explicar como se construye el árbol, primero definamos el ancestro dere-


cho mas joven del nodo(i) como adj(i), que es el número de nodo del padre del
mas joven de los ancestros del nodo(i) que es hijo derecho, (En la figura adj(11)
es 0). Si un nodo no posee adj entonces su adj es -1 (menos uno).

10
1.8 Árboles binarios de hasheo

El árbol binario es construido en orden numeral. ı́ndice(0) es seteado a h(clave).


ı́ndice(i), para cada subsiguiente i, es seteado a rh(ı́ndice((i - 1)/2), clave(adj(i))).
Este proceso continua hasta que clave(i) iguala CLAVENULA y una posición vacı́a
es encontrada en la tabla.

Una ves que el árbol a sido construido, las claves de los caminos desde la raı́z
hasta los últimos nodos son reordenados en la tabla de hasheo. emphi es inicializa-
do en la posición del ultimo nodo del árbol. Luego si adj(i) no es cero, clave(adj(i))
y su registro asociado es movido desde la tabla[(ı́ndice(adj(i)))] a tabla[ı́ndice(i)]
y i es reseteado a adj(i). Este proceso es repetido hasta que adj(i) es -1(menos
uno), en cuyo caso clave y registro son insertado en tabla[ı́ndice(i)] y la inserción
esta completa.

Cuando buscamos subsecuentemente por claves, dos posiciones de tablas son


probadas: a y b. Cuando buscamos por la tabla[b].clave, dos comprobaciones más
son requeridas. Cuando buscamos por tabla[k].clave una comprobación es requeri-
da. Un total de 5(cinco) posiciones son comprobadas, en toda la tabla de hasheo,
cuando insertamos una clave; mientras que 6(seis) son requeridas si hubiera sido
insertada en su camino de rehasheo.

Vemos que todo el algoritmo depende de la función que encuentra el adj(i). Es-
ta puede derivar del siguiente método para que se realice rápidamente: Encontrar
la representación binaria de i + 1. Borrar cualquier TRAILING de 0(cero) bits y
1 bits precediéndolos. Restar 1(uno) del resultado del número binario a obtener su
adj(i). Por ejemplo : la representación de 11(once) + 1(uno) es 1100. removiendo el
TRAILING de 100 se llega a 1; entonces adj(11) = 0, adj(17) = 3, adj(14) = 6, etc.

Gonnet y Munro obtienen resultados que se son más cercanos al óptimo que el
algoritmo de Brent. De cualquier forma no son óptimos, ya que los elementos de

11
2 El Contenedor Asociativo de Hasheo de la Biblioteca Estándar de Plantillas
(STL)

tabla de hasheo solo pueden ser reordenados moviéndolos a posiciones mas altas
de la tabla y nunca a las posiciones más bajas. Cuando la tabla esta cargada en
factor 0,9, el árbol binario requiere 1,75 comprobaciones por obtención (en Brent
1.80), con un factor de 0,95 requiere 1.88 (en Brent 1,97). Para una √ tabla llena
requiere un promedio de 2,13 y Brent 2,5. Mientras que Brent es O( 2 n) el Árbol
Binario de Hasheo es de O(log n).

2. El Contenedor Asociativo de Hasheo de la


Biblioteca Estándar de Plantillas (STL)
2.1. Tipos nuevos del Contenedor
El contenedor asociativo de hasheo es lo que nos brinda la STL para manejar
hashing. Junto con este contenedor aparecen dos tipos de datos mas: X::hasher()
que nos da un modelo de función de hasheo cuyo argumento es del tipo key type, y
X::value type la cual nos da la función de comparación o comprobación de claves,
que tiene un predicado binario cuyo argumento debe ser del tipo X::key type. Con
esta última un objeto del tipo key equal es devuelto si los argumentos de la función
son la misma clave, y falso de otra forma. X::key equal debe ser una relación de
equivalencia.

2.2. Notación
X es un Tipo que es un modelo de Contenedor Asociativo de Hasheo.

a es un Objeto del tipo X.

t es un Objeto del tipo X::value type.

k es un Objeto del tipo X::key type.

p,q son Objetos del tipo X::iterator.

n es un Objeto del tipo X::size type.

h es un Objeto del tipo X::hasher.

c es un Objeto del tipo X::key equal

12
2.3 Definiciones

2.3. Definiciones
Los elementos del Contenedor Asociativo de Hasheo son organizados en bucket
(buckets). El contenedor utiliza el valor de la función de Hasheo para determinar
a cual bucket se le asignará.

2.4. Funciones del Contenedor :

2.5. Garantı́as de complejidad


El contenedor nos brinda ciertas garantı́as de complejidad para las operaciones
de sus funciones, las cuales son :

Todos los constructores son amortizados en un tiempo constante.

Las funciones de comprobación y de hasheo están amortizadas en tiempo con-


stante.

13
2.6 Modelos en el contenedor :

La complejidad promedio para eliminar una clave es de O(count(clave)). En el


peor caso es lineal con el tamaño del contenedor.

Borrar elementos esta amortizado en tiempo constante.

El promedio de complejidad para borrar un rango es de O(n), donde n es la


longitud del rango.

El promedio de complejidad para la búsqueda es de tiempo constante. En el


peor por caso es lineal con el tamaño del contenedor.

El promedio de complejidad para la comparación de rangos es de O(count(clave)).


El peor caso es lineal con el tamaño del Contenedor.

El conteo de bucket esta amortizado en tiempo constante.

Cambiar el tamaño del Contenedor es lineal con el tamaño del contenedor.

2.6. Modelos en el contenedor :


hash set: Guarda claves del tipo Key. Pertenece también al Contenedor Aso-
ciativo Único; no permite que dos claves comparen igual.

hash map: Asocia objetos del tipo Key con objetos del tipo Data. Pertenece
también al Contenedor de Pares Asociados lo que significa que su tipo de valor es
pair¡const Key, Data¿.También es un Contenedor Asociativo Único.

hash multiset: Es un Contenedor Asociativo Múltiple que permite dos o más


claves comparen de la misma forma.

hash multimap: Posee las mismas funciones que el hash map pero es un Con-
tenedor Asociativo Múltiple.

3. Bibliografı́a
Andrew S. Tanenbaum - ”Structured Computer Organization, 4th ed.”
http://www.cs.vu.nl/ ast/

14
3 Bibliografı́a

Donal Ervin Knuth - ”The Art Of Computer Programming” - Volume 3 - Sort-


ing and Searching - Second Edition - 1998.

Silicon Graphics Computer Systems, Inc. - Standard Template Library Pro-


grammer’s Guide -
http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi/srch24@
standar %20template %20library/0650/bks/SGI Developer/books/
STL PG/sgi html/index.html

Kruse - ”Data Structures And Program Design”- 1st Edition - Prentice-Hall,


Inc. - 1984.

Kruse - ”Data Structures And Program Design In C++” - 1st Edition - Prentice-
Hall, Inc. - 2000

Menezes, van Oorschot, Vanstone - ”Handbook Of Applied Cryptography” -


CRC Press - 1997.
http://www.cacr.math.uwaterloo.ca/hac

Sedgewick; ”Algorithms” - Addison-Wesley - 1983.

15