lunes, 12 de agosto de 2013

Conozcamos la STL (Standard Template Library) de C++ - Primera entrega: std::map - Parte 1 de 2

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.

No hay comentarios.:

Publicar un comentario