web-dev-qa-db-fra.com

Insertion dans un vecteur à l'avant

iterator insert ( iterator position, const T& x );

Est la déclaration de fonction de l'opérateur d'insertion de std::Vector classe.

Le type de retour de cette fonction est un itérateur pointant vers l'élément inséré. Ma question est, compte tenu de ce type de retour, quel est le moyen le plus efficace (cela fait partie d'un programme plus large que j'exécute où la vitesse est essentielle, donc je recherche le le plus moyen de calcul efficace ) d'insertion au début. Est-ce le suivant?

//Code 1
vector<int> intvector;
vector<int>::iterator it;
it = myvector.begin();
for(int i = 1; i <= 100000; i++){
    it = intvector.insert(it,i);
}

Ou,

//Code 2
vector<int> intvector;
for(int i = 1; i <= 100000; i++){
    intvector.insert(intvector.begin(),i);
}

Essentiellement, dans le code 2, est le paramètre,

intvector.begin() 

"Coûteux" à évaluer par rapport à l'utilisation de l'itérateur retourné dans le code 1 ou les deux devraient-ils être tout aussi bon marché/coûteux?

42
Tryer

L'efficacité de l'obtention du point d'insertion n'aura aucune importance - elle sera éclipsée par l'inefficacité de mélanger constamment les données existantes à chaque fois que vous effectuez une insertion.

Utilisez std :: deque pour cela, c'est pour cela qu'il a été conçu.

41
Mark Ransom

Si l'un des besoins critiques de votre programme est pour insérer des éléments au début d'un conteneur: alors vous devez utiliser un std::deque et non un std::vector. std::vector ne sert qu'à insérer des éléments à la fin.

STL diagram for choosing containers

D'autres conteneurs ont été introduits dans C++ 11. Je devrais commencer à trouver un graphique mis à jour avec ces nouveaux conteneurs et l'insérer ici.

114
Stephane Rolland

Un vieux fil, mais il est apparu au bureau d'un collègue comme premier résultat de recherche pour une requête Google.

Il existe une alternative à l'utilisation d'un deque qui mérite d'être envisagée:

std::vector<T> foo;
for (int i = 0; i < 100000; ++i)
  foo.Push_back(T());
std::reverse( foo.begin(), foo.end() );

Vous utilisez toujours un vecteur beaucoup plus conçu que deque pour les performances. De plus, les swaps (qui sont les utilisations inverses) sont assez efficaces. En revanche, la complexité, bien que toujours linéaire, est augmentée de 50%.

Comme toujours, mesurez avant de décider quoi faire.

28

Le plus probable deque est la solution appropriée comme suggéré par d'autres. Mais juste pour être complet, supposons que vous devez effectuer cette insertion frontale une seule fois, qu'ailleurs dans le programme, vous n'avez pas besoin d'effectuer d'autres opérations sur le front, et qu'autrement vector fournit l'interface dont vous avez besoin . Si tout cela est vrai, vous pouvez ajouter les éléments avec le très efficace Push_back puis reverse le vecteur pour tout mettre en ordre. Cela aurait une complexité linéaire plutôt que polynomiale comme lors de l'insertion à l'avant.

12
Mark B

Si vous recherchez un moyen d'insertion efficace sur le plan informatique, vous voudrez probablement utiliser un deque au lieu d'un vecteur.

12
Tim Rupe

Je pense que vous devriez changer le type de votre conteneur si vous voulez vraiment insérer des données au début. C'est la raison pour laquelle le vecteur n'a pas de fonction membre Push_front ().

2
Hongseok Yoon

Lorsque vous utilisez un vecteur, vous connaissez généralement le nombre réel d'éléments qu'il contiendra. Dans ce cas, réserver le nombre d'éléments nécessaires (100000 dans le cas que vous montrez) et les remplir en utilisant le [] L'opérateur est le moyen le plus rapide. Si vous avez vraiment besoin d'un insert efficace à l'avant, vous pouvez utiliser deque ou list, selon vos algorithmes.

Vous pouvez également envisager d'inverser la logique de votre algorithme et de l'insérer à la fin, ce qui est généralement plus rapide pour les vecteurs.

2
Diego Sevilla

Intuitivement, je suis d'accord avec @Happy Green Kid Naps et j'ai effectué un petit test montrant que pour les petites tailles (1 << 10 éléments d'un type de données primitif), cela n'a pas d'importance. Pour les contenants plus grands (1 << 20), cependant, std::deque semble être plus performant que l'inversion d'un std::vector. Donc, comparez avant de vous décider. Un autre facteur pourrait être le type d'élément du conteneur.

  • Test 1: Push_front (a) 1 << 10 ou (b) 1 << 20 uint64_t dans std :: deque
  • Test 2: Push_back (a) 1 << 10 ou (b) 1 << 20 uint64_t dans std :: vector suivi de std :: reverse

Résultats:

  • Test 1 - deque (a) 19 µs
  • Test 2 - vecteur (a) 19 µs
  • Test 1 - deque (b) 6339 µs
  • Test 2 - vecteur (b) 10588 µs
0
Marie Hoffmann