Jak odwrócić wektor C ++?


144

Czy istnieje wbudowana funkcja wektorowa w C ++ do odwracania wektora w miejscu?

A może po prostu musisz to zrobić ręcznie?

Odpowiedzi:


251

Służy do tego funkcja std::reversew algorithmnagłówku.

#include <vector>
#include <algorithm>

int main() {
  std::vector<int> a;
  std::reverse(a.begin(), a.end());
  return 0;
}

Czy możesz wyjaśnić, jak odwrócić wektor wektorów? Chcę, aby v [0] zostało zamienione na v [v.size () - 1], a kolejność elementu v [0] [i] pozostanie niezmieniona. Jest to podobne do zmiany kolejności wierszy (jeśli wektor jest postrzegany jako macierz). Jeśli wektor jest zdefiniowany jako: wektor <wektor <int>> v; reverse (v.begin (), v.end ()) nie odwraca tego. TIA!
— Vikas Goel

@VikasGoel faktycznie sugerowany fragment powinien działać. Może jest jakiś inny problem?
— Ivaylo Strandjev

45

Wszystkie kontenery oferują odwrócony widok zawartości za pomocą rbegin()i rend(). Te dwie funkcje zwracają tak zwane odwrotne iteratory , których można używać jak normalnych, ale będzie wyglądać tak, jakby kontener był faktycznie odwrócony.

#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(), "<-");
}

Przykład na żywo w Ideone . Wynik:

1->2->3->4->5
=============
5<-4<-3<-2<-1

1
to jednak nie odwraca wektora w miejscu. Możesz stworzyć nowy wektor za pomocą std :: vector <T> v2 (v1.rbegin (), v1.rend ()); v2.swap (v1); które efektywnie wykorzystałyby Twoje rozwiązanie. Nie widzę jednak, czy użycie std :: reverse jest bardziej eleganckie lub w jakikolwiek sposób korzystne.
— CashCow

17
@CashCow: Cóż, po pierwsze, to nie jest operacja, to O (1). Cofanie… nie tak bardzo. W większości przypadków tak naprawdę nie potrzebujesz odwróconego kontenera, wystarczy, że zobaczysz go jako odwrócony. W rzeczywistości nie przychodzi mi do głowy sytuacja, w której faktycznie potrzebujesz odwróconego kontenera, którego nie można rozwiązać za pomocą odwrotnych iteratorów.
— Xeo,

4
@CashCow: Elegancja nie zawsze jest prawdziwą elegancją. W większości przypadków w mojej karierze zawodowej potrzebowałem tylko odwróconego spojrzenia, ale nie odwróconego wektora. We wszystkich tych przypadkach wydajność byłaby całkowicie niepotrzebna, gdybyś utworzył więcej kopii lub zmienił kolejność. Czy chciałbyś również std::sortmieć wektor 1000 elementów, jeśli potrzebujesz tylko pierwszej dziesiątki w nieokreślonej kolejności, ponieważ jest bardziej elegancki niż std::partition? To jest szkoła myślenia, która paraliżuje moje doświadczenie z komputerem, tak jak 15 lat temu, z tą różnicą, że jeszcze więcej cykli jest zmarnowanych, miliardy z nich.
— Sebastian Mach

print_rangenie jest poprawne: nie zadziała, jeśli zostanie przekazany pusty zakres.
— Nawaz,

więc najważniejsze pytanie brzmi: co std::reverse(a.rbegin(), a.rend())zrobi? ; ^)
— Orwellophile

23

Możesz używać w std::reverseten sposób

std::reverse(str.begin(), str.end());

5
To zdumiewające, jaką różnicę robią dwie minuty.
— jww

2

Możesz także użyć std::listzamiast std::vector. listposiada wbudowaną funkcję list :: reverse do odwracania elementów.


3
std :: list powinno być preferowane w stosunku do wektora w jedynym szczególnym przypadku wstawiania wielu elementów w dowolne pozycje w sekwencji. Używanie std :: list zamiast wektora tylko dlatego, że odwrócisz sekwencję, jest złym pomysłem z punktu widzenia wydajności.
— eozd

0

Często powodem, dla którego chcesz odwrócić wektor, jest to, że wypełniasz go, wciskając wszystkie elementy na końcu, ale w rzeczywistości otrzymywałeś je w odwrotnej kolejności. W takim przypadku możesz odwrócić pojemnik w trakcie podróży, używając dequezamiast tego i popychając je bezpośrednio z przodu. (Lub możesz vector::insert()zamiast tego wstawiać elementy z przodu za pomocą , ale byłoby to powolne, gdy jest dużo elementów, ponieważ musi tasować wszystkie inne elementy przy każdym wstawianiu). W przeciwieństwie do:

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

Zamiast tego możesz:

std::deque<int> foo;
int nextItem;
while (getNext(nextItem)) {
    foo.push_front(nextItem);
}
// No reverse needed - already in correct order

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
}

1
Czy to pytanie sprzed ośmiu lat wymaga kolejnej zduplikowanej odpowiedzi, która niczego nie wnosi?
— Blastfurnace
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.