Ce que je veux dire, c'est que nous savons que les éléments de std::map
Sont triés en fonction des clés. Alors, disons que les clés sont des entiers. Si j'itère de std::map::begin()
à std::map::end()
à l'aide de for
, la norme garantit-elle que j'itérerai en conséquence à travers les éléments avec les clés, triés par ordre croissant?
Exemple:
std::map<int, int> map_;
map_[1] = 2;
map_[2] = 3;
map_[3] = 4;
for( std::map<int, int>::iterator iter = map_.begin();
iter != map_.end();
++iter )
{
std::cout << iter->second;
}
Est-ce que cela garantit d’imprimer 234
Ou est-ce que l’implémentation est définie?
Raison réelle: J'ai un std::map
Avec les clés int
. Dans de très rares situations, j'aimerais parcourir tous les éléments, avec une clé supérieure à une valeur concrète int
. Oui, il semble que std::vector
Serait le meilleur choix, mais remarquez mes "situations très rares".
EDIT : Je sais que les éléments de std::map
sont triés. Inutile de le préciser (pour la plupart des réponses ici) . Je l'ai même écrit dans ma question.
Je posais des questions sur les itérateurs et la commande lorsque je parcourais un conteneur. Merci @Kerrek SB pour la réponse.
Oui, c'est garanti. De plus, *begin()
vous donne le plus petit et *rbegin()
le plus grand élément, comme déterminé par l'opérateur de comparaison, ainsi que deux valeurs de clé a
et b
pour dont l'expression !compare(a,b) && !compare(b,a)
est vraie sont considérés comme égaux. La fonction de comparaison par défaut est std::less<K>
.
L’ordre n’est pas un bonus, mais un aspect fondamental de la structure de données, car il permet de déterminer quand deux clés sont identiques (par la règle ci-dessus) et d’effectuer une recherche efficace (essentiellement une méthode binaire). recherche, qui présente une complexité logarithmique dans le nombre d'éléments).
Ceci est garanti par les exigences du conteneur associatif dans la norme C++. Par exemple. voir 23.2.4/10 en C++ 11:
La propriété fondamentale des itérateurs de conteneurs associatifs est qu'ils Parcourent les conteneurs dans l'ordre non décroissant des clés, où Non décroissant est défini par la comparaison utilisée. pour les construire. Pour deux itérateurs déréférencables i et j tels que la distance de i à j soit positive, value_comp (* j, * i) == faux
et 23.2.4/11
Pour les conteneurs associatifs avec des clés uniques, la condition la plus forte est vérifiée, Value_comp (* i, * j)! = False.
Je pense qu'il y a une confusion dans les structures de données.
Dans la plupart des langues, un map
est simplement un conteneur associatif: il mappe une clé sur une valeur. Dans les "nouvelles" langues, ceci est généralement réalisé en utilisant une carte de hachage, donc aucun ordre n'est garanti.
En C++, cependant, il n'en est rien:
std::map
est un conteneur associatif triéstd::unordered_map
est un conteneur associatif basé sur une table de hachage introduit en C++ 11Donc, afin de clarifier les garanties sur la commande.
En C++ 03:
std::set
, std::multiset
, std::map
et std::multimap
sont garantis à commander en fonction des clés (et du critère fourni)std::multiset
et std::multimap
, la norme n'impose aucune garantie d'ordre à des éléments équivalents (c'est-à-dire, ceux qui se comparent égaux)En C++ 11:
std::set
, std::multiset
, std::map
et std::multimap
sont garantis à commander en fonction des clés (et du critère fourni)std::multiset
et std::multimap
, la norme impose que les éléments équivalents (ceux qui se comparent égaux) soient ordonnés en fonction de leur ordre d'insertion (premier inséré en premier)std::unordered_*
_ Les conteneurs ne sont pas commandés, comme leur nom l’indique. Plus particulièrement, l'ordre des éléments peut changer lorsque le conteneur est modifié (lors de l'insertion/suppression).Lorsque la norme dit que les éléments sont ordonnés d'une manière, cela signifie que:
J'espère que cela dissipe toute confusion.
Est-ce que cela garantit d’imprimer 234 ou si sa mise en œuvre est définie?
Oui, std::map
est un conteneur trié, commandé par le Key
avec le Comparator
fourni. Donc c'est garanti.
Je voudrais aller parcourir tous les éléments, avec la clé, supérieure à une valeur int concrète.
C'est sûrement possible.
Oui ... les éléments d'un std::map
Ont un ordre faible strict, ce qui signifie qu'ils seront composés d'un ensemble (c'est-à-dire qu'il n'y aura pas de répétition de clés "égales") et d'égalité. est déterminé en testant sur deux clés A et B quelconques, que si la clé A n'est pas inférieure à la clé B et que B n'est pas inférieure à A, la clé A est égale à la clé B.
Cela étant dit, vous ne pouvez pas trier correctement les éléments d'un std::map
Si l'ordre faible de ce type est ambigu (dans votre cas, vous utilisez des entiers comme type de clé, ce n'est pas un problème) . Vous devez être capable de définir une opération définissant un ordre total sur le type que vous utilisez pour les clés de votre std::map
. Sinon, vous n'aurez qu'un ordre partiel pour vos éléments, ou poset, qui a une propriété où A peut ne pas être comparable à B. Ce qui se passera généralement dans ce scénario est que vous pourrez insérer les paires clé/valeur, mais que vous risquez de vous retrouver avec des paires clé/valeur en double si vous parcourez toute la carte./ou détectez des paires clé/valeur "manquantes" lorsque vous essayez d'effectuer une std::map::find()
d'une paire clé/valeur spécifique dans la carte.