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?

SirYakalot
źródło

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;
}
Ivaylo Strandjev
źródło
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
Xeo
źródło
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());
Chuck Norris
źródło
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.

Witam W.
źródło
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
Arthur Tacca
źródło
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
źródło
1
Czy to pytanie sprzed ośmiu lat wymaga kolejnej zduplikowanej odpowiedzi, która niczego nie wnosi?
Blastfurnace