Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Tema 5 Tablas
Tema 5 Tablas
AVANZADOS II:
TABLAS
(MAPAS/DICCIONARIOS)
Tema 5
1. Fundamentos.
Tema 4. 2. Representación.
3. Representación mediante C++/STL.
Tablas 4. Aplicaciones.
2
Definición
Clave Valor
t: Clave Valor
t es una Tabla
– Ejemplo:
Operaciones:
t_nula: → Tabla
asignar: Tabla, Clave, Valor → Tabla
consultar: Tabla, Clave → Valor Puede implicar Buscar
definida: Tabla, Clave → 𝔹𝔹
■ Array:
float v[100];
– Clave = 0..99
– Valor = float
■ vector:
#include <vector>
vector<float> v;
– Clave = unsigned int
– Valor = float
■ Árboles Binarios de Búsqueda: C++
#include <map>
– ABB a; map<TipoClave,TipoInfo> a;
– Clave = ABB::TipoClave
Árboles Rojo-Negro (Red-Black Trees)
– Valor = ABB::TipoInfo ABB + criterio de autoequilibrio
C V
x 0
x x
…
x xx
k p = f(k)
x
x
x
x
x x
x
p v[p] = valor
x
x x
x
x
x
…
asociado con k
x x
x x
x
x x
x m-1
C V
x 0
x x
f(c) .
x xx
x
x
x
NO
.
x x x
x
x x
.
x x x
x
x x
x x
x
x x
x m-1
V
C x 0
x x
g(c) .
x
x x
x x
x
x
x
x
x x
x . SI
.
x x x
x x
x
x x
x
x x
x m-1
𝑓𝑓1 𝑐𝑐 = � 𝑐𝑐𝑖𝑖 % 𝑚𝑚
∀𝑐𝑐𝑖𝑖 ∈𝑐𝑐
𝑓𝑓1 𝑐𝑐 = � 𝑐𝑐𝑖𝑖 % 𝑚𝑚
∀𝑐𝑐𝑖𝑖 ∈𝑐𝑐
■ Considerar 𝑝𝑝 = 32 (=25):
𝑓𝑓2 𝑐𝑐 = � 𝑐𝑐𝑖𝑖 . 32𝑖𝑖 %m
∀𝑐𝑐𝑖𝑖 ∈𝑐𝑐
peso asociado a cada posición de la clave = 320, 321, 322, 323, …
■ Calcular x*32 = desplazar 5 bits a la izquierda el valor x.
– Calcular x* 322 = desplazar 10 bits a la izquierda el valor x.
– Calcular x* 323 = desplazar 15 bits a la izquierda el valor x.
– …
■ El orden de los caracteres en la clave es importante:
𝑓𝑓2 "𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎𝑎 = 3.608.367 ≠ 𝑓𝑓2 "𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟𝑟 = 4.221.391
≠ 𝑓𝑓2 "𝑚𝑚𝑚𝑚𝑚𝑚𝑚𝑚𝑚 = 4.041.871
■ Claves alfanuméricas (‘a’..’z’, ‘A’..’Z’, ‘0’..’9’), máx. longitud 16.
– 𝑓𝑓2 (c) genera valores en el rango [48.. 4,75771E+24]
■ Criptografía y Seguridad:
– Una función de hashing transforma un valor arbitrario dentro
de un conjunto de elementos en un valor numérico de
longitud fija.
– A partir del valor numérico obtenido NO es posible revertir el
proceso (obtener el valor original que lo ha generado).
■ Ejemplo: Aplicar función de hash sobre todo un fichero de texto.
– La clave a transformar es todo el fichero (!!!).
– Se obtiene como resultado un valor numérico, que se puede
usar como “resumen” (huella) del documento.
– El valor hash del documento se puede distribuir de forma
segura porque no permite recuperar el documento original.
– El valor hash permite comparar y asegurar la veracidad de un
documento.
■ SHA-3, última versión del estándar Secure Hash Algorithm.
■ Cada posición del array mantiene una lista de (Clave, Valor) con
los elementos que colisionan en esa posición.
■ Para localizar un valor hay que acceder a la posición del array y
buscar secuencialmente la clave en la lista correspondiente.
0
1
2
3
f ( c ) = c % 10 4
5
Insertar (89, “A”)
9 6
7
8 clave valor
9 89 A
0
1
2
3
f ( c ) = c % 10 4
5
Insertar (18, “B”)
8 6
7 clave valor
8 18 B
9 89 A
0
1
2
3
f ( c ) = c % 10 4
5
Insertar (49, “C”)
6
9
7
8 18 B
9 49 C 89 A
0
1
2
3
f ( c ) = c % 10 4
8 6
7
8 58 D 18 B
9 49 C 89 A
0
1
2
3
f ( c ) = c % 10 4
5
9 6
Insertar (69, “E”)
7
8 58 D 18 B
9 69 E 49 C 89 A
clave valor
Insertar {89, 18, 49, 58, 69}
0
1
2
3
f ( c ) = c % 10 4
5
Insertar (89, “A”)
9 6
7
8
9 89 A
clave valor
Insertar {89, 18, 49, 58, 69}
0
1
2
3
f ( c ) = c % 10 4
5
Insertar (18, “B”)
8 6
7
8 18 B
9 89 A
clave valor
Insertar {89, 18, 49, 58, 69}
0
1
2
3
f ( c ) = c % 10 4
5
Insertar (49, “C”)
9 6
7
8 18 B
9 89 A
Colisión:
Prueba 0 falla,
Realizar siguiente prueba en posición (9 + 1) % 10
clave valor
Insertar {89, 18, 49, 58, 69}
0 49 C
0 1
2
3
f ( c ) = (c % 10 + i) % 10 4
5
Insertar (49, “C”)
6
7
8 18 B
9 89 A
clave valor
Insertar {89, 18, 49, 58, 69}
0 49 C
1
2
3
f ( c ) = (c % 10 + i) % 10 4
5
Insertar (58, “D”)
8 6
7
8 18 B
9 89 A
Colisión:
Prueba 0 falla,
Realizar siguiente prueba en posición (8 + 1) % 10
clave valor
Insertar {89, 18, 49, 58, 69}
0 49 C
1
2
3
f ( c ) = (c % 10 + i) % 10 4
5
Insertar (58, “D”)
6
9
7
8 18 B
9 89 A
Colisión:
Prueba 1 falla,
Realizar siguiente prueba en posición (8 + 2) % 10
clave valor
Insertar {89, 18, 49, 58, 69}
0 49 C
0 1
2
3
f ( c ) = (c % 10 + i) % 10 4
5
Insertar (58, “D”)
6
7
8 18 B
9 89 A
Colisión:
Prueba 2 falla,
Realizar siguiente prueba en posición (8 + 3) % 10
clave valor
Insertar {89, 18, 49, 58, 69}
0 49 C
1 58 D
1 2
3
f ( c ) = (c % 10 + i) % 10 4
5
Insertar (58, “D”)
6
7
8 18 B
9 89 A
clave valor
Insertar {89, 18, 49, 58, 69}
0 49 C
1 58 D
2
3
f ( c ) = (c % 10 + i) % 10 4
5
Insertar (69, “E”)
6
9 7
8 18 B
9 89 A
Colisión:
Prueba 0 falla,
Realizar siguiente prueba en posición (9 + 1) % 10
clave valor
Insertar {89, 18, 49, 58, 69}
0 49 C
0 1 58 D
2
3
f ( c ) = (c % 10 + i) % 10 4
5
Insertar (69, “E”)
6
7
8 18 B
9 89 A
Colisión:
Prueba 1 falla,
Realizar siguiente prueba en posición (9 + 2) % 10
clave valor
Insertar {89, 18, 49, 58, 69}
0 49 C
1 58 D
1
2
3
f ( c ) = (c % 10 + i) % 10 4
5
Insertar (69, “E”)
6
7
8 18 B
9 89 A
Colisión:
Prueba 2 falla,
Realizar siguiente prueba en posición (9 + 3) % 10
clave valor
Insertar {89, 18, 49, 58, 69}
0 49 C
1 58 D
2 2 69 E
3
f ( c ) = (c % 10 + i) % 10 4
5
Insertar (69, “E”)
6
7
8 18 B
9 89 A
clav dat
Insertar {89, 18, 49, 58, 69} e o
0 49 C
1 58 D
2 69 E
3
4
f ( c ) = ( c % 10 + i ) % 10
5
6
7
Las claves que han colisionado en las
posiciones 8 y 9 se han agrupado, formando 8 18 B
una secuencia en las posiciones 8, 9, 0, 1, 2. 9 89 A
El resto de la tabla está vacía.
■ Buscar:
– Hashing + Buscar en la secuencia de posiciones definida por
la estrategia (lineal, cuadrática, doble dispersión) hasta
encontrar la clave o un hueco libre.
– Puede finalizar con éxito (clave encontrada) o con fracaso
(clave no encontrada).
■ Fracaso = Se alcanza una posición libre.
– Factor de carga de la tabla, λ = n/m (claves almacenadas/nº
de posiciones en la tabla) ≡ Fracción de celdas ocupadas.
■ Fracción de celdas libres = 1 – λ
– Número esperado de pruebas para encontrar una posición
1
libre:
1−𝜆𝜆
1 1
ln
λ 1− λ
43
Implementación en C++ (Clase)
// Tabla Hash con Encadenamiento
class Tabla
{
public:
//Declaracion de los tipos clave y valor
typedef string TipoClave; //sustituir por lo que corresponda
typedef string TipoDato; //sustituir por lo que corresponda
class ParDato //Los datos almacenados en la tabla (Clave, Valor)
{
public:
TipoClave clave;
TipoDato valor;
ParDato(){}
ParDato (TipoClave a, TipoDato b)
:clave(a),valor(b) {}
};
//Operaciones
Tabla(size_t); //t_nula
bool Buscar(TipoClave, TipoDato&) const; //consultar/definida
void Insertar(const ParDato&); //asignar
private:
vector< vector<ParDato> > t; //Encadenamiento
size_t Hash(TipoClave) const;
};
private:
//Encadenamiento, cada posición del vector t es un vector.
vector<vector<TipoParDato>> t;
//Función de dispersión.
size_t Hash(TipoClave) const;
};
ind = Hash(cl);
j = 0;
while ( j<t[ind].size() && !enc ) //Búsq. secuencial en el vector t[ind]
if ( t[ind][j].clave == cl )
{
va = t[ind][j].valor;
enc = true;
}
else j++;
return enc;
}
if (! Buscar (tmp.clave,tmp.valor) )
//Añadir al final del vector correspondiente
t[Hash(x.clave)].push_back(x);
}
ind = Hash(cl);
j = 0;
while ( j < t[ind].size() && ! enc ) //Búsqueda secuencial en el vector
if (t[ind][j].first == cl )
{
va = &t[ind][j].second; //Dirección del valor encontrado
enc = true;
}
else j++;
if ( !enc )
{
//Añadir al final del vector correspondiente con un dato por defecto
t[ind].push_back(make_pair(cl,TipoDato()));
va = &t[ind][t[ind].size()-1].second; //Dirección del valor añadido
}
return *va; //valor referenciado por va
}
ind = Hash(cl);
j = 0;
while ( j < t[ind].size() && ! enc ) //Búsq. secuencial en el vector t[ind]
if (t[ind][j].first == cl )
enc = true;
else j++;
return enc;
}
50
TAD Tabla en C++ (STL)
■ En la biblioteca estándar de C++ (STL) podemos encontrar
diversos contenedores que responden al TAD Tabla:
ABB rojo-negro
– map: Tabla con clave única.
– multimap: Tabla que admite duplicado de claves.
– set: Conjunto. Es una tabla que únicamente contiene claves.
– multiset: Conjunto con elementos repetidos.
Tablas hash con encadenamiento
– unordered_map
– unordered_multimap
– unordered_set
– unordered_multiset
#include <map>
map<string,int> m;
– Opción 2: Operador []
m[“juan”] = 3;
– Opción 2: Operador []
cout << m[“juan”];
Importante: si “juan” no existe, lo crea sin valor asociado (!!!).
map<string,int>::iterator it;
for ( it = m.begin(); it != m.end(); it++ )
cout << “clave:” << it->first << “ dato:”
<< it->second << endl;
cout << "str: " << str << " valor hash: " << f_hash(str) << endl;
return 0;
}
57
Hashing espacial