Як повернути вектор 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] залишиться таким, яким він є. Це схоже на зміну порядку рядків (якщо вектор розглядається як Матриця). Якщо вектор визначений як: вектор <вектор <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має вбудований список функцій :: реверс для елементів реверсу.


3
std :: list слід віддавати перевагу над вектором у єдиному конкретному випадку вставки багатьох елементів у довільні положення у послідовності. Використання std :: списку над вектором тільки тому, що ви переймете послідовність - це погана ідея.
еозд

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