Обращение массива (вектора) с использованием reverse_iterator - PullRequest
1 голос
/ 17 июня 2019

Я пытаюсь улучшить свои знания c ++, используя вызовы Edabit и тестируя «новые» функции.Текущий вызов хочет, чтобы мы написали функцию для обращения к массиву.примеры:

reverse([1, 2, 3, 4]) ➞ [4, 3, 2, 1]

reverse([9, 9, 2, 3, 4]) ➞ [4, 3, 2, 9, 9]

reverse([]) ➞ []

Я пытался сделать это с помощью reverse_iterator, но у меня есть какой-то странный результат.

std::vector<int> reverse(std::vector<int> arr) {
    std::vector<int> out;
    for(std::vector<int>::reverse_iterator i = arr.rbegin(); i != arr.rend(); ++i)
    {
        out.push_back(arr[*i]);
    }
    return out;
}

Результат, который я получаю, следующий:

FAILED: Expected: equal to [ 4, 3, 2, 1 ]
Actual: [ 0, 4, 3, 2 ]

Сначала кажется, что это был только один раз, o я добавил 1 с помощью rbegin () и сделал rend следующим образом:

for(std::vector<int>::reverse_iterator i = arr.rbegin() + 1; i != arr.rend() + 1; ++i)

И кажется, что первый тест пройден, но следующий тест кажется далеко:

FAILED: Expected: equal to [ 7, 6, 5 ]
Actual: [ 33, 0, 5 ]

Я пытаюсь понять, как работает этот обратный итератор, поэтому, пожалуйста, предоставьте решение и некоторые четкие объяснения, почему первый тест прошел с добавлением 1 и почему второй не прошел.

Ответы [ 3 ]

7 голосов
/ 17 июня 2019

Попробуйте:

for(std::vector<int>::reverse_iterator i = arr.rbegin(); i != arr.rend(); ++i)
{
    out.push_back(*i);
}

Итератор уже дает вам значение, а не индекс для вектора.

1 голос
/ 17 июня 2019

Предпочитайте алгоритмы в стандартной библиотеке как можно больше для ручной обработки циклов, потому что:
1) они более выразительны;
2) они могут быть более эффективными.

std::reverse(std::begin(arr), std::end(arr));

Просто включите заголовок «алгоритма», чтобы использовать std :: reverse.

1 голос
/ 17 июня 2019

Выражение в индексе оператора

out.push_back(arr[*i]);
              ^^^^^^^   

не имеет смысла.

Вы имеете в виду

out.push_back( *i );

Но в любом случае функцию можно написать лучше, например, так, чтобы создать новый перевернутый вектор

#include <iostream>
#include <vector>
#include <iterator>


std::vector<int> reverse( const std::vector<int> &v ) 
{
    std::vector<int> out;
    out.reserve( v.size() );

    for ( auto first = std::rbegin( v ), last = std::rend( v ); first != last; ++first )
    {
        out.push_back( *first );
    }

    return out;
}

int main() 
{
    std::vector<int> v = { 4, 3, 2, 1 };

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout << '\n';

    auto reversed_v = reverse( v );

    for ( const auto &item : reversed_v ) std::cout << item << ' ';
    std::cout << '\n';

    return 0;
}

Вывод программы

4 3 2 1 
1 2 3 4

Или вот так, чтобы обратить вектор на место

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>


void reverse( std::vector<int> &v ) 
{
    if ( not v.empty() )
    {
        for ( auto first = std::rbegin( v ), last = std::rend( v ); first < --last; ++first )
        {
            std::iter_swap( first, last );
        }
    }       
}

int main() 
{
    std::vector<int> v = { 4, 3, 2, 1 };

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout << '\n';

    reverse( v );

    for ( const auto &item : v ) std::cout << item << ' ';
    std::cout << '\n';

    return 0;
}

Вывод программы такой же, как показано выше

4 3 2 1 
1 2 3 4

В качестве альтернативы есть соответствующие стандартные алгоритмы std::reverse_copy и std::reverse, которые вы можете использовать вместо них.

...