web-dev-qa-db-fra.com

Différence entre std :: list <std :: pair> et std :: map en C ++ stl

Pouvez-vous me dire la différence entre std :: list <std :: pair> et std :: map. Puis-je également utiliser la méthode find sur la liste?

Je vous remercie.

- Clarification

Question modifiée pour être plus claire.

38
Boolean

std::map<X, Y>:

  • est une structure ordonnée par rapport aux clés (c'est-à-dire que lorsque vous itérez dessus, les clés augmenteront toujours).
  • prend en charge les clés uniques (Xs) uniquement
  • offre une méthode rapide find() (O(log n)) qui trouve la paire valeur-clé par clé
  • propose un opérateur d'indexation map[key], qui est également rapide

std::list<std::pair<X, Y> >:

  • est une simple séquence de Xs et Ys appariés. Ils restent dans l'ordre dans lequel vous les avez placés.
  • peut contenir n'importe quel nombre de doublons
  • trouver une clé particulière dans un list est O(N) (pas de méthode spéciale)
  • propose la méthode splice.
109
jpalecek

std::pair

std::pair est une structure de tuple modélisée limitée à 2 éléments, appelée premier et deuxième:

std::pair<int, std::string> myPair ;
myPair.first = 42 ;
myPair.second = "Hello World" ;

std::pair est utilisé comme "conteneur générique" par la STL (et un autre code) pour agréger deux valeurs en même temps sans avoir à redéfinir un autre struct.

std::map

std::map est un conteneur associatif basé sur un modèle, associant des clés et des valeurs ensemble. L'exemple le plus simple (mais pas plus efficace) est:

std::map<int, std::string> myMap ;
myMap[42] = "Fourty Two" ;
myMap[111] = "Hello World" ;
// ...
std::string strText ;  // strText is ""
strText = myMap[111] ; // strText is now "Hello World"
strText = myMap[42] ;  // strText is now "Fourty Two"
strText = myMap[23] ;  // strText is now "" (and myMap has
                       // a new value "" for key 23)

std::pair et std::map

Remarque: Il s'agit de la réponse à la question d'origine non modifiée.

Le std::map les fonctions doivent retourner les itérateurs aux clés et aux valeurs en même temps pour rester efficaces ... La solution évidente est donc de retourner les itérateurs aux paires:

std::map<int, std::string> myMap ;
myMap[42] = "Fourty Two" ;
myMap[111] = "Hello World" ;

myMap.insert(std::make_pair(23, "Bye")) ;

std::map<int, std::string>::iterator it = myMap.find(42) ;
std::pair<int, std::string> keyvalue = *it ;    // We assume 42 does
                                                // exist in the map
int key = keyvalue.first ;
int value = keyvalue.second ;

std::list<std::pair<A,B> > et std::map<A,B>

Remarque: modifié après l'édition de la question.

Ainsi, à première vue, une carte de paires et une liste de paires semblent identiques. Mais ce n'est pas le cas:

La carte est intrinsèquement ordonnée par le foncteur fourni, tandis que la liste gardera les paires de [A, B] là où vous les avez placées. Cela rend l'insertion O (log n) pour la carte, tandis que l'insertion brute à l'intérieur d'une liste est une complexité constante (chercher où l'insérer est un autre problème).

Vous pouvez simuler quelque peu le comportement d'une carte à l'aide d'une liste de paires, mais notez que la carte est généralement implémentée comme une arborescence d'éléments, tandis que la liste est une liste chaînée d'éléments. Ainsi, un algorithme comme la dichotomie fonctionnera beaucoup plus rapidement dans une carte que dans une liste.

Ainsi, trouver un élément dans une carte est O (log n), alors que dans une liste non ordonnée, c'est O (n). Et si la liste est ordonnée et que vous souhaitez utiliser la dichotomie, vous n'obtiendrez pas l'augmentation de performance attendue, car la traversée de la liste des éléments est effectuée élément par élément de toute façon.

(Dans un projet sur lequel j'ai travaillé il y a un an, nous avons remplacé une liste d'articles commandés par un ensemble des mêmes articles commandés, et cela a amélioré les performances. L'ensemble ayant la même arborescence interne que la carte, je suppose que le même boost s'appliquerait ici)

20
paercebal

(Modifié après clarification)

std::map Est optimisé pour une recherche rapide. Il possède sa propre méthode find qui utilise sa structure interne pour fournir de bonnes performances. En général, il inspectera uniquement les touches log(N), où N est le nombre d'éléments dans la carte.

std::list<std::pair> Est une simple liste chaînée, et ne prend donc en charge que la traversée élément par élément. Vous pourriez utiliser l'algorithme std::find Séparé ou std::find_if Avec un prédicat personnalisé qui examine uniquement le membre first pour mieux correspondre à la sémantique de std::map::find, Mais ce serait très lent. En fait, il devra regarder chaque paire dans la liste pour toute recherche ayant échoué, et en regarder la moitié en moyenne pour toute recherche réussie.

3
Walter Mundt

std:pair contient exactement deux objets. std:map contient une collection d'objets appariés.

Vous ne pouvez pas utiliser find () sur une paire, car il n'y a rien à trouver. L'objet que vous voulez est soit pair.First ou pair.Second

MISE À JOUR: En supposant que vous vouliez dire la différence entre map<> et list<pair<> >: La carte doit être implémentée pour une recherche rapide sur le membre key. list a juste une simple liste linéaire. La recherche d'un élément dans une liste nécessite de parcourir toute la liste. Cependant, std :: find () fonctionnera sur les deux.

2
James Curran

Les cartes STL sont des tableaux associatifs, généralement implémentés en tant que hashmaps à l'intérieur. Si vous souhaitez obtenir une itération sur une carte STL, elle renverra une paire STL.

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
        map<string, int> myMap;
        myMap["myKey"] = 1337;

        map<string, int>::iterator myIterator = myMap.begin();

        pair<string, int> myPair = *myIterator;

        cout<<"the key \""<<myPair.first<<"\" maps to the value of "<<myPair.second<<endl;
        cout<<"the key \"myKey"\" maps to the value of "<<myMap["myKey"]<<endl;
        return 0;
}

Je suggérerais de googler et de lire la référence complète de l'API STL car STL (à l'exception du stockage des booléens dans des vecteurs et autres bizarreries comme ça) implémente beaucoup de fonctionnalités de structure de données que vous voudriez utiliser dans n'importe quel programme sans réinventer la roue.

1
Novikov

La carte peut fournir le meilleur temps de recherche dans la plage de O (log n), tandis que la liste peut avoir le temps de recherche de O (n).

0
Udhay

std :: pair sert uniquement à regrouper exactement 2 objets (par exemple, "les coordonnées sur une page" sont composées de X et Y).

std :: map est un mappage d'un ensemble d'objets à un autre.

Il ne sert à rien d'essayer d'utiliser une méthode de recherche sur une paire, comme à quoi sert de trouver quelque chose dans une liste de deux choses dont vous connaissez l'ordre, même si cette méthode de recherche existait dans une classe de paires, ce qu'elle ne fait pas.

Cependant, vous POUVEZ utiliser std :: pair comme valeur de carte si c'est ce que vous voulez.

0
DVK