Qual é a diferença entre std :: multimap <key, value> e std :: map <key, std :: set <value>>

Respostas:

52

O multimapa armazena pares de (chave, valor) onde a chave e o valor podem aparecer várias vezes.

O map<key, set<value>>irá armazenar cada valor apenas uma vez para uma chave específica. Para fazer isso, ele deverá ser capaz de comparar os valores, não apenas as chaves.

Depende do seu aplicativo se os valores que comparam iguais são equivalentes ou se você deseja armazená-los separadamente. Talvez eles contenham campos diferentes, mas não participem da comparação do conjunto.

Bo Persson
fonte
5
Portanto, um std :: multimap <chave, valor> é como um std :: map <chave, std :: multiset <valor>>, a diferença entre eles é que os últimos valores são classificados. Isso está certo?
大 宝剑
2
Não, std::multimap<key, value>permite que a mesma chave apareça várias vezes, mas std::map<key, whatever>requer a exclusividade de key.
Yixing Liu
74

A std::mapé um contêiner associativo, que permite que você tenha uma chave exclusiva associada ao valor do tipo. Por exemplo,

void someFunction()
{
    typedef std::map<std::string, int> MapType;
    MapType myMap;

    // insertion
    myMap.insert(MapType::value_type("test", 42));
    myMap.insert(MapType::value_type("other-test", 0));

    // search
    auto it = myMap.find("test");
    if (it != myMap.end())
        std::cout << "value for " << it->first << " is " << it->second << std::endl;
    else
        std::cout << "value not found" << std::endl;
}

A std::multimapé igual a a std::map, mas suas chaves não são mais exclusivas. Portanto, você pode encontrar uma variedade de itens em vez de apenas encontrar um item exclusivo. Por exemplo,

void someFunction()
{
    typedef std::multimap<std::string, int> MapType;
    MapType myMap;

    // insertion
    myMap.insert(MapType::value_type("test", 42));
    myMap.insert(MapType::value_type("test", 45));
    myMap.insert(MapType::value_type("other-test", 0));

    // search
    std::pair<auto first, auto second> range = myMap.equal_range("test");
    for (auto it = range.first; it != range.second; ++it)
        std::cout << "value for " << it->first << " can be " << it->second << std::endl;
}

O std::seté como um std::map, mas não está armazenando uma chave associada a um valor. Ele armazena apenas o tipo de chave e garante que ele é único dentro do conjunto.

Você também tem o std::multiset, que segue o mesmo padrão.

Todos esses contêineres fornecem um acesso O (log (n)) com seu find / equal_range.

typedef
fonte
6
Na função multimapa, esta linha std::pair<auto first, auto second> range = myMap.equal_range("test");não funciona, porque error: 'auto' not allowed in template argument. Use em seu const auto range = myMap.equal_range("test")lugar.
vancexu
2
tipo de mapa? Não deveria ser MapType na linha 4?
lolololol de
não tenho certeza de quem foi o primeiro, mas um é obviamente uma cópia e pasta do outro: cppbuzz.com/What-is-difference-between-map-and-multimap
idclev 463035818
1
ahah, cppbuzz está raspando StackOverflow ou o quê ?, eu mesmo escrevi esta resposta anos atrás, quando eu ainda estava codificando diariamente em c ++. E realmente há um erro de digitação na linha 4, obrigado @lololololol
typedef
1
(e sua cópia / colagem falhou, eles nem mesmo exibem os tipos no template std :: map declaração: std :: map <std :: string, int>)
typedef
13
map::insert

Como os mapcontêineres não permitem valores de chave duplicados, a operação de inserção verifica para cada elemento inserido se outro elemento já existe no contêiner com o mesmo valor de chave. Nesse caso, o elemento não é inserido e seu valor mapeado não é alterado de nenhuma maneira.

por outro lado

multimap::insert 

pode inserir qualquer número de itens com a mesma chave.

http://www.cplusplus.com/reference/stl/map/
http://www.cplusplus.com/reference/stl/multimap/

Luka Rahne
fonte
Bom link sobre a diferença e como funciona internamente. link
Rndp13
10

O último requer que os valores possam ser ordenados (por meio de operator<ou por uma função de comparação), o primeiro não.

Björn Pollex
fonte
Pareceria que o operador <funciona da mesma forma no mapa ou no multimapa? en.cppreference.com/w/cpp/container/map/operator_cmp
johnbakers
Sim, mas minha resposta referia-se à ordenação dos valores. Suponha que você tenha um tipo Tsem ordenação. Você pode usá-lo para criar um std::multimap<U, T>, mas não pode usar para criar um std::map<U, std::set<T> >.
Björn Pollex