Как я могу обратить вектор C ++?


144

Есть ли в C ++ встроенная векторная функция для обратного вектора?

Или вам просто нужно сделать это вручную?

Ответы:


251

Для этого std::reverseв algorithmзаголовке есть функция .

#include <vector>
#include <algorithm>

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

Не могли бы вы объяснить, как обратить вектор векторов? Я хочу, чтобы v [0] поменялся местами с v [v.size () - 1] и порядок элемента v [0] [i] остался как есть. Это похоже на изменение порядка строк (если вектор рассматривается как матрица). Если вектор определен как: vector <vector <int>> v; reverse (v.begin (), v.end ()) не меняет его. ТИА!
Викас Гоэль

@VikasGoel на самом деле фрагмент, который вы предлагаете, должен работать. Может быть, есть какая-то другая проблема?
Ивайло Странджев

45

Все контейнеры предлагают обратный просмотр их содержимого с помощью rbegin()и rend(). Эти две функции возвращают так называемые обратные итераторы , которые можно использовать как обычные, но похоже, что контейнер фактически перевернут.

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

Живой пример на Ideone . Вывод:

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

1
это, однако, не меняет вектор на месте. Вы можете создать новый вектор с помощью std :: vector <T> v2 (v1.rbegin (), v1.rend ()); v2.swap (v1); который бы эффективно использовал ваше решение. Я не понимаю, как это более элегантно или выгодно в любом случае использовать std :: reverse.
CashCow

17
@CashCow: Ну, во-первых, это бездействие, это O (1). Задний ход .. не так много. Большую часть времени вам не нужен перевернутый контейнер, вам нужно только видеть его перевернутым. На самом деле, я не могу вспомнить ситуацию, когда вам действительно нужен обратный контейнер, который не может быть решен с помощью обратных итераторов.
Xeo

4
@CashCow: элегантность не всегда истинная элегантность. В большинстве случаев в моей профессиональной карьере я просто нуждался в обратном взгляде, но не в обратном направлении. И во всех этих случаях производительность будет совершенно бесполезной, если вы создадите больше копий или измените порядок. Вы бы также std::sortвектор 1000 элементов, если вам просто нужно топ-10 в неопределенном порядке, потому что он более элегантный, чем std::partition? Это школа мысли, которая наносит вред моему опыту работы с ПК сегодня, как это было 15 лет назад, с той разницей, что еще больше циклов потрачено впустую, миллиарды из них.
Себастьян Мах

print_rangeне правильно: он не будет работать при пропуске пустого диапазона.
Наваз

так что большой вопрос, что будет std::reverse(a.rbegin(), a.rend())делать? ; ^)
Орвеллофил

23

Вы можете использовать std::reverseкак это

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

5
Это удивительная разница, которую делают две минуты.
jww

2

Вы также можете использовать std::list вместо std::vector. listимеет встроенную функцию list :: reverse для реверсирования элементов.


3
std :: list должен быть предпочтительнее вектора в единственном конкретном случае вставки множества элементов в произвольные позиции в последовательности. Использование std :: list над vector только потому, что вы перевернете последовательность, является плохой идеей с точки зрения производительности.
февраля

0

Часто причина, по которой вы хотите повернуть вектор, заключается в том, что вы заполняете его, нажимая на все элементы в конце, но фактически получаете их в обратном порядке. В этом случае вы можете перевернуть контейнер по ходу движения, используя dequeвместо этого и толкая их прямо вперед. (Или vector::insert()вместо этого вы можете вставить элементы впереди , но это будет медленно, когда есть много элементов, потому что для каждой вставки необходимо перетасовывать все остальные элементы.) Так что вместо:

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

Вы можете вместо этого сделать:

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
Нужен ли этот восьмилетний вопрос еще один повторяющийся ответ, который ничего не добавляет?
Доменная печь
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.