Comment inverser un vecteur C ++?

144

Existe-t-il une fonction vectorielle intégrée en C ++ pour inverser un vecteur en place?

Ou devez-vous simplement le faire manuellement?

SirYakalot
la source

Réponses:

251

Il y a une fonction std::reversedans l'en- algorithmtête à cet effet.

#include <vector>
#include <algorithm>

int main() {
  std::vector<int> a;
  std::reverse(a.begin(), a.end());
  return 0;
}
Ivaylo Strandjev
la source
Pourriez-vous expliquer comment inverser le vecteur des vecteurs? Je veux que v [0] soit échangé avec v [v.size () - 1] et l'ordre de l'élément v [0] [i] reste tel quel. Ceci est similaire à la modification de l'ordre des lignes (si un vecteur est considéré comme une matrice). Si un vecteur est défini comme: vecteur <vecteur <int>> v; reverse (v.begin (), v.end ()) ne l'inverse pas. TIA!
Vikas Goel le
@VikasGoel en fait, l'extrait que vous suggérez devrait fonctionner. Il y a peut-être un autre problème?
Ivaylo Strandjev
45

Tous les conteneurs offrent une vue inversée de leur contenu avec rbegin()et rend(). Ces deux fonctions renvoient des itérateurs inversés , qui peuvent être utilisés comme des fonctions normales, mais il semblera que le conteneur est en fait inversé.

#include <vector>
#include <iostream>

template<class InIt>
void print_range(InIt first, InIt last, char const* delim = "\n"){
  --last;
  for(; first != last; ++first){
    std::cout << *first << delim;
  }
  std::cout << *first;
}

int main(){
  int a[] = { 1, 2, 3, 4, 5 };
  std::vector<int> v(a, a+5);
  print_range(v.begin(), v.end(), "->");
  std::cout << "\n=============\n";
  print_range(v.rbegin(), v.rend(), "<-");
}

Exemple en direct sur Ideone . Production:

1->2->3->4->5
=============
5<-4<-3<-2<-1
Xeo
la source
1
cela n'inverse cependant pas le vecteur en place. Vous pouvez créer un nouveau vecteur avec std :: vector <T> v2 (v1.rbegin (), v1.rend ()); v2.swap (v1); qui utiliserait efficacement votre solution. Cependant, je ne vois pas en quoi il est plus élégant ou avantageux d'utiliser std :: reverse.
CashCow
17
@CashCow: Eh bien, d'une part, c'est un no-op, c'est O (1). Inverser ... pas tellement. La plupart du temps, vous n'avez pas vraiment besoin d'un conteneur inversé, il vous suffit de le voir comme inversé. En fait, je ne peux pas penser à une situation où vous avez réellement besoin d'un conteneur inversé qui ne peut pas être résolu avec des itérateurs inversés.
Xeo
4
@CashCow: L'élégance n'est pas toujours la vraie élégance. Dans la plupart des cas dans ma carrière professionnelle, j'avais juste besoin d'une vue inversée, mais pas d'un vecteur inversé. Et dans tous ces cas, les performances souffriraient totalement inutilement si vous créiez plus de copies ou transformiez la commande. Souhaitez-vous également std::sortun vecteur de 1000 éléments, si vous avez juste besoin du top-10 dans un ordre non spécifié, car il est plus élégant que std::partition? C'est l'école de pensée qui paralyse mon expérience informatique aujourd'hui comme elle le faisait il y a 15 ans, à la différence que davantage de cycles sont gaspillés, des milliards d'entre eux.
Sebastian Mach
print_rangen'est pas correct: cela ne fonctionnera pas lorsque la plage vide est passée.
Nawaz
donc la grande question est, que va std::reverse(a.rbegin(), a.rend())faire? ; ^)
Orwellophile
23

Vous pouvez utiliser std::reversecomme ça

std::reverse(str.begin(), str.end());
Chuck Norris
la source
5
C'est incroyable la différence que font deux minutes.
jww
2

Vous pouvez également utiliser à la std::listplace de std::vector. lista une fonction intégrée list :: reverse pour inverser les éléments.

Bonjour W
la source
3
std :: list doit être préféré à vector dans le seul cas spécifique d'insertion de nombreux éléments à des positions arbitraires dans la séquence. Utiliser std :: list sur vector simplement parce que vous inverserez la séquence est une mauvaise idée en termes de performances.
eozd
0

Souvent, la raison pour laquelle vous souhaitez inverser le vecteur est que vous le remplissez en appuyant sur tous les éléments à la fin, mais que vous les receviez dans l'ordre inverse. Dans ce cas, vous pouvez inverser le conteneur au fur et à mesure en utilisant un à la dequeplace et en le poussant directement sur le devant. (Ou vous pouvez insérer les éléments à l'avant avec à la vector::insert()place, mais ce serait lent quand il y a beaucoup d'éléments car il doit mélanger tous les autres éléments le long de chaque insertion.) Donc, par opposition à:

std::vector<int> foo;
int nextItem;
while (getNext(nextItem)) {
    foo.push_back(nextItem);
}
std::reverse(foo.begin(), foo.end());

Vous pouvez à la place faire:

std::deque<int> foo;
int nextItem;
while (getNext(nextItem)) {
    foo.push_front(nextItem);
}
// No reverse needed - already in correct order
Arthur Tacca
la source
0
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
int main()
{
    vector<int>v1;
    for(int i=0; i<5; i++)
        v1.push_back(i*2);
    for(int i=0; i<v1.size(); i++)
        cout<<v1[i];    //02468
    reverse(v1.begin(),v1.end());
    
    for(int i=0; i<v1.size(); i++)
        cout<<v1[i];   //86420
}
Bashar
la source
1
Cette question vieille de huit ans a-t-elle besoin d'une autre réponse en double qui n'ajoute rien?
Blastfurnace