std::map
std::map
é uma classe genérica do tipo contentor associativo ordenado.
Vejamos,
classe genérica | podem ser definidos map de vários
tipos (tal como já tinha sido observado com a utilização das classes
vector e list , por exemplo), ou
seja, é genérica; |
contentor | permite guardar vários itens (neste caso, pares (chave, valor)); |
associativo | estabelece uma relação entre dois tipos (um par, portanto), em que o primeiro elemento do par é a chave e o segundo é o valor correspondente; |
ordenado | existe uma relação de ordem no conjunto dos valores da chave. |
Para utilizar a classe genérica map
, deverá acrescentar usar
a seguinte directiva de inclusão:
#include <map>
No texto que se segue assume-se que se usou a directiva de utilização
using namespace std;
pelo que se omite o prefixo std::
.
A classe genérica map
deve ser parametrizada com os tipos dos
elementos dos pares que irá guardar. Por exemplo, map<string,
unsigned>
é uma classe de mapa (diz-se uma instanciação da classe
genérica map
) cujos itens são pares (string
, unsigned
).
Assim, para definir um mapa m
cujos itens são pares do tipo (Chave
,
Valor
), usa-se a seguinte instrução:
map<Chave, Valor> m;
Podem usar-se mapas para criar estruturas de dados mais complexas. Por exemplo:
map<int, map<int, double> > m;
define um mapa m
que associa a chaves do tipo int
valores do tipo
map<int, double>
, que por sua vez associa a chaves do tipo int
valores do tipo double
.
Atenção: Deve sempre existir um espaço entre o primeiro
>
e o segundo >
em qualquer definição deste
tipo.
Listam-se em seguida algumas das operações mais importantes das classes map<Chave,
Valor>
(instanciadas a partir da classe genérica map
).
map<Chave, Valor>::operator[]
//
Devolve por referência o valor associado à chavec
.
Valor
& map<Chave, Valor>::operator[](Chave const& c);
map<string, unsigned> telefones; //
Define um mapa vazio.
telefones["João"] = 212121212; //
Acrescenta ao mapa o par (João, 212121212).
telefones["Joana"] = 961234567; //
Acrescenta ao mapa o par (Joana, 961234567).
telefones["João"] = 917654321; //
Substitui no mapa o par (João, 212121212) por
//
(João, 917654321).
cout << telefones["Joana"] << endl;
//
Aparece "961234567" no ecrã.
Quando o acesso se faz através de uma chave que não consta ainda no mapa, é inserido automaticamente um par (chave, valor) com a chave dada e com o valor por omissão do valor:
cout << telefones["Felizberto"] << endl;
//
Aparece "0" no ecrã.
Repare-se que falamos sempre de pares, mas nunca "vimos" um. No entanto, é possível trabalhar directamente com pares. Um par pode ser definido da seguinte forma:
string nome("Maria");
pair<string, unsigned> telefone(nome, 931234567);
//
Oupair<string, unsigned> telefone(make_pair(nome, 931234567));
Para aceder à chave (primeiro elemento do par), deve usar-se a seguinte instrução:
cout << "Chave: " << telefone.first << endl; //
Aparece no ecrã "Maria".
Para aceder ao valor (segundo elemento do par), deve usar-se a seguinte instrução:
cout << "Valor: " << telefone.second << endl; //
Aparece no ecrã "931234567".
map<Chave, Valor>::insert()
Para inserir pares (chave, valor), pode-se usar os pares com a classe genérica map
como se segue:
/*
Devolve um par (map<Chave, Valor>::iterator, bool
), em que o
iterador referencia a posição onde o par
par
foi inserido e obool
étrue
, caso a
inserção tenha sido bem sucedida; caso já exista um elemento com chave
par.first
,
o iterador referencia a posição desse elemento e o
bool
tem o valorfalse
.*/
pair<map<Chave, Valor>::iterator, bool> map<Chave, Valor>::
insert(pair<Chave const, Valor> const& par);
Exemplos:
pair<map<string, unsigned>::iterator, bool> resultado =
telefones.insert(telefone);
if(not resultado.second)
Aparece "inseri" no ecrã
cout << "não ";
cout << "inseri" << endl;
//
resultado = telefones.insert(make_pair(nome, 217654321));
if(not p.second)
Aparece "não inseri" no ecrã, pois a inserção falha se existe já um par com a
cout << "não ";
cout << "inseri" << endl;
//
//
mesma chave.
map<Chave, Valor>::find()
e
map<Chave, Valor>::count()
Para saber se um par existe e para o procurar, podem-se usar as seguintes operações:
/*
Devolve o número de pares cuja chave échave
. No caso dos mapas devolve
sempre 0 ou 1. Há uma outra classe genérica,
multimap
, que permite chaves
repetidas, para a qual esta operação pode devolver valores superiores a 1.
*/
map<Chave, Valor>::size_type map<Chave, Valor>::count(Chave const& chave);
//
Devolve um iterador constante para o par cuja chave échave
. Caso a chave não
exista devolve o iterador para o item fictício final:
map<Chave, Valor>::const_iterator map<Chave, Valor>::find(Chave const& c) const;
map<Chave, Valor>::iterator map<Chave, Valor>::find(Chave const& c);
Exemplos:
string nome("Maria");
if(telefones.count(nome) != 0)
cout << nome << " ..... " << telefones.find("Maria")->second << endl;
else
cout << nome << " ..... (não encontrado)" << endl;
//
ou
if(telefones.find(nome) != telefones.end())
cout << nome << " é " << telefones.find("Maria")->second << endl;
else
cout << nome << " não encontrado" << endl;
map<Chave, Valor>::erase()
Para remover um par de um mapa pode-se usar a seguinte operação:
/*
Remove o par com a chavechave
, devolvendo o número de pares removido
(0 ou 1). Infelizmente é uma operação dois-em-um.
*/
map<Chave, Valor>::size_type map<Chave, Valor>::erase(const Chave& chave);
Exemplo:
if(telefones.erase("João") == 0)
cout << "O joão não constava da lista..." << endl;
cout << telefones.count("João") << endl;
//
Aparece "0" no ecrã.
Como percorrer todos os itens de um map
? Tal como com
na classe genérica vector
, podemos usar iteradores para percorrer os
itens de um
mapa. O ciclo abaixo percorre todos os itens do mapa map<string, unsigned> telefones
por ordem crescente da chave:
typedef map<string, unsigned>::const_iterator Iterador;
for(Iterador i = telefones.begin(); i != telefones.end(); ++i)
cout << i->first << ' ' << i->second << endl;
Atenção: Como foi referido no início, tem de existir uma relação de ordem no
conjunto dos valores da chave, pelo que o operador <
deve existir para
o tipo da chave.