Introducción
Mucha personas (como yo en el pasado cercano) ignorarán el poder oculto detrás de las siglas STL. Se trata de nada más ni nada menos que una de las "cosas" que convierte a C++ en uno de los lenguajes de programación más poderosos. La STL o Standard Template Library
La STL proporciona una colección de estructuras de datos contenedoras y algoritmos genéricos que se pueden utilizar con éstas.
(tomado de aquí: http://decsai.ugr.es/~jfv/ed1/c++/cdrom4/paginaWeb/stl.htm)
En esta entrega trataré de ilustrar el uso del contenedor map, a través de algunos ejemplos prácticos.
Dada la extensión que pretendía dar a este tema, decidí dividirlo en dos entradas independientes y complementarias.
La primera parte de esta entrega (es decir, este post) consiste en la implementación del contenedor std::map con los tipos de datos incluidos en el estándar de C++.
En la segunda parte (disponible aquí) abordaré la implementación del contenedor std::map haciendo uso de una clase propia, es decir, una clase que hemos hecho nosotros mismos, tal como lo ilustramos en una entrega previa, donde hemos definido una clase para la manipulación de vectores.
Contenedor std::map de la STL
Generalidades del contenedor std::map
Uno de esos contenedores incluidos en la STL corresponde a map, un contenedor de datos donde cada uno posee una clave(key en inglés) que lo identifica. Para utilizar map es necesario incluirlo en la cabecera de nuestro código fuente:
#include<map>
De esta manera, es posible hacer el llamado
std::map<tipo_variable_1 clave,tipo_variable_2 valor, criterio_comparación_clave> variable_map;
De esta manera, se puede declarar una varible tipo
map, en este caso:
variable_map. Esta definición parece un poco ambigua de entender, pero todo es más claro en cuanto se entiende que la variable
map lo que hace es etiquetar con la variable
clave lo que contiene la variable
valor. Para realizar el ordenamiento, el contenedor
map utiliza un criterio de comparación basándose en alguna
operación de comparación, específicamente, usando el
operador< definido para del
tipo_variable_1, es por esta razón que el operador< debe estar definido para el tipo de variable utilizado como
clave.
Para realizar la asignación de valores a nuestro mapa, basta con escribir
variable_map[valor_tipo_variable_1]=valor_tipo_variable_2;
Para ver claramente lo que acabo de exponer, observemos el siguiente ejemplo (código c++, obviamente)
#include<iostream>
#include<string>
#include<map>
int main(void)
{
std::map<int /*indice o clave*/, std::string /*contenido*/> mi_mapa;
std::string palabra;
for(int i(0);i<5;i++)
{
std::cout << "Ingrese una palabra: " << std::endl;
std::cin>>palabra;
mi_mapa[i]=palabra;
}
for(i=0;i<5;i++)
{
std::cout << "Palabra almacenada con clave " << i << " es " << mi_mapa[i] << std::endl;
}
}
Vemos que en el ejemplo hemos usado
map como si se tratase de un
array. Sin embargo, la diferencia sustancial es que la información se ha guardado de manera ordenada en función del valor de
i. Este comportamiento no es visible a simple vista, puesto que el orden de entrada de los datos ya están ordenados, pero considere el siguiente ejemplo
#include<iostream>
#include<string>
#include<map>
int main(void)
{
std::map<int /*indice o clave*/, std::string /*contenido*/> mi_mapa;
std::string palabra;
int numero;
for(int i(0);i<5;i++)
{
std::cout << "Ingrese un número: " << std::endl;
std::cin >> numero;
std::cout << "Ingrese una palabra: " << std::endl;
std::cin >> palabra;
mi_mapa[numero]=palabra;
}
for(i=0;i<5;i++)
{
std::cout << "Palabra almacenada con clave " << i << " es " << mi_mapa[i] << std::endl;
}
}
En este caso, vemos que para cada valor no repetido de i, se muestra un valor de palabra. es decir, que para cada int i, se ha asignado una variable std::string. Este uso sigue siento familiar con el uso de los arrays. Podemos probar cambiando los tipos de variable en la definición de la variable tipo map. Considere el siguiente ejemplo
#include<iostream>
#include<string>
#include<map>
int main(void)
{
std::map<std::string /*indice_palabra*/,int /*indice_numero*/
> mi_mapa;
std::string palabra;
int numero;
mi_mapa["hola"]=10;
mi_mapa["alfabeto"]=5;
mi_mapa["zoo"]=0;
mi_mapa["a"]=3;
mi_mapa["marmota"]=9;
std::cout << " La palabra \"alfabeto\" tiene asignado el número " << mi_mapa["alfabeto"] << std::endl;
std::cout << " La palabra \"a\" tiene asignado el número " << mi_mapa["a"] << std::endl;
std::cout << " La palabra \"hola\" tiene asignado el número " << mi_mapa["hola"] << std::endl;
std::cout << " La palabra \"marmota\" tiene asignado el número " << mi_mapa["marmota"] << std::endl;
}
A cada
std::string se ha asignado un valor numérico tipo
int, de esta manera, los llamados a cada
int se realizan mediante el
std::string correspondiente a su
clave.
Considere ahora el siguiente ejemplo
#include<iostream>
#include<string>
#include<map>
int main(void)
{
std::map<std::string /*indice_palabra*/,int /*indice_numero*/
> mi_mapa;
std::string palabra;
int numero;
for(int i(0);i<5;i++)
{
std::cout << "Ingrese un número: " << std::endl;
std::in >> numero;
std::cout << "Ingrese una palabra: " << std::endl;
std::in >> palabra;
mi_mapa[palabra]=numero;
std::cout << " La palabra << palabra << " tiene asignado el número " << mi_mapa[palabra] << std::endl;
}
}
En este caso, a cada palabra ingresada por el usuario, se ha asignado un valor numérico también ingresado por el usuario. El ordenamiento se hace según el operador< definido en la clase std::string.