web-dev-qa-db-fra.com

L'ordre d'itération std :: set est-il toujours croissant selon la spécification C ++?

Ici http://www.cplusplus.com/reference/stl/set/ J'ai lu que std :: set en C++ est "typiquement" implémenté comme un arbre (un rouge-noir?) Et il est trié.

Je ne pouvais pas comprendre, cela signifie-t-il que par spécification l'ordre d'itération de l'ensemble est toujours croissant? Ou s'agit-il uniquement de "détails d'implémentation habituels" et parfois, certaines bibliothèques/compilateurs peuvent violer cette convention?

32
Rodion Gorkovenko

Selon la norme C++, itération sur les éléments dans un std::set procède dans un ordre trié déterminé par std::less ou par l'argument de modèle de prédicat de comparaison facultatif.

(Toujours selon la norme C++, l'insertion, la recherche et la suppression prennent au maximum O (lg n) temps, donc les arbres de recherche équilibrés sont actuellement le seul choix d'implémentation viable pour std::set, même si l'utilisation d'arbres rouge-noir n'est pas imposée par la norme.)

45
Fred Foo

Cela signifie qu'en interne std::set stockera ses éléments sous forme d'arbre trié. Cependant, la spécification ne dit rien sur l'ordre de tri. Par défaut, std::set les usages std::less et ainsi passera de bas en haut. Cependant, vous pouvez faire en sorte que la fonction de tri soit celle que vous voulez, en utilisant ce paramètre de modèle:

std::set<valueType, comparissonStruct> myCustomOrderedSet;

Ainsi, par exemple:

std::set<int, std::greater<int> > myInverseSortedSet;

ou

struct cmpStruct {
  bool operator() (int const & lhs, int const & rhs) const
  {
    return lhs > rhs;
  }
};

std::set<int, cmpStruct > myInverseSortedSet;

En fait, ces exemples sont également fournis sur le site Web que vous avez lié. Plus précisément ici: set constructor .

21
Darhuuk

Le comparateur par défaut est inférieur, donc l'ensemble sera ordonné croissant. Pour changer cela, vous pouvez spécifier un autre comparateur existant ou personnalisé comme argument de modèle.

3
Marian Petre

Projet standard C++ 11 N3337

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf

23.2.4 "Conteneurs associatifs" dit:

1 Les conteneurs associatifs permettent une récupération rapide des données en fonction des clés. La bibliothèque propose quatre types de base de conteneurs associatifs: set, multiset, map et multimap.

et:

10 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 descendant est défini par la comparaison qui a été utilisée pour les construire.

donc oui , l'ordre est garanti par le standard C++.

C'est pourquoi gcc 6.4.0 l'implémente par exemple en tant que BST au lieu de hashmap: Quelle est la structure de données sous-jacente d'un ensemble STL en C++?

Comparez cela avec C++ 11 unordered_set, ce qui tend à fournir de meilleures performances avec une implémentation de hashmap, au prix d'être plus restreint (pas de traversée triée libre) comme indiqué à:

par spécification, l'ordre d'itération de l'ensemble est toujours croissant

Oui, les valeurs de set sont toujours croissantes si vous les imprimez en séquence. Comme le dit la description, il est généralement implémenté à l'aide de Red-Black Tree (RBT), mais les rédacteurs du compilateur ont la possibilité de violer cela, mais généralement ils s'en tiendraient au thème de RBT car toute autre implémentation ne sera pas efficace en termes de ressources pour atteindre la tâche de set.

2
Shamim Hafiz