Форум » C/C++ для начинающих (C/C++ for beginners) » Выполнение инверсии строк матрицы или в частном случае двух-мерного массива. » Ответить
Выполнение инверсии строк матрицы или в частном случае двух-мерного массива.
Сыроежка: Эта тема создана на основе вопроса на Stackoverflow How to swap rows or columns in a two dimensional array? Автор вопроса спрашивает, как выполнить инверсию строк или колонок матрицы. В заголовке вопросе он ссылается на двух-мерный массив хотя в приведенном примере кода, включенном в вопрос, он имеет дело не с двух-мерным массивом, а с динамически созданном массивом массивов. А также его пример имеет дело лишь с проблемой выполнения инверсии строк матрицы, а не колонок. Поэтому именно инверсия строк матрицы и будет рассмотрена в этой теме. Автор вопроса приводит пример того, что он хочет получить. То есть если имеется матрица вида [pre2] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4 5 5 5 5 5 [/pre2] то нужно получить матрицу вида [pre2] 5 5 5 5 5 4 4 4 4 4 3 3 3 3 3 2 2 2 2 2 1 1 1 1 1 [/pre2] Очевидно, для начинающего программиста это задание на умение использовать обычные for-циклы. Но в данной теме рассмотрим, как можно выполнить поставленное задачу с использованием стандартных алгоритмов вместо циклов. Для начала рассмотрим, как сделать инверсию строк именно для двух-мерного массива. Практически, все задание можно выполнить с помощью стандартных алгоритмов. Ниже представлена демонстрационная программа для данного случая. [pre2] #include <iostream> #include <iterator> #include <algorithm> int main() { const size_t N = 5; int a[N][N]; int i = 1; for ( auto &row : a ) std::fill( std::begin( row ), std::end( row ), i++ ); for ( const auto &row : a ) { std::copy( std::begin( row ), std::end( row ), std::ostream_iterator<int>( std::cout, " " ) ); std::cout << '\n'; } std::cout << '\n'; std::reverse( std::begin( a ), std::end( a ) ); for ( const auto &row : a ) { std::copy( std::begin( row ), std::end( row ), std::ostream_iterator<int>( std::cout, " " ) ); std::cout << '\n'; } std::cout << '\n'; } [/pre2] Вывод программы на консоль: [pre2] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 4 4 4 4 4 3 3 3 3 3 2 2 2 2 2 1 1 1 1 1 [/pre2] То есть используя стандартный алгоритм std::reverse для двух-мерного массива, можно выполнить инверсию его строк, так как функция std::swap также определена для массивов. В этой программе можно было бы также заменить все for предложения на основе диапазона на вызов стандартного алгоритма std::for_each. Например, вывод массива на консоль можно было бы сделать следующим образом [pre2] auto display_row = []( const auto &row ) { std::copy( std::begin( row ), std::end( row ), std::ostream_iterator<int>( std::cout, " " ) ); std::cout << '\n'; }; std::for_each( std::begin( a ), std::end( a ), display_row ); std::cout << '\n'; [/pre2] Однако следует не увлекаться вызовом алгоритма std::for_each вместо использования предложения for на основе диапазона. Иногда код с использованием предложения for на основе диапазона выглядит более ясным и читабельным, чем использование алгоритма std::for_each, когда объект функции, используемый в этом алгоритме, является чрезмерно сложным и громоздким. Теперь рассмотрим, случай, имеющий место в исходном вопросе, когда динамически создается массив массивов. В этом случае программа усложняется тем, что нужно выделить память для массивов и затем не забыть ее удалить. Но и в этом случае достаточно применить алгоритм std:;reverse для элементов "внешнего" массива, которые имеют тип указателей. Ниже представлена соответствующая демонстрационная программа. [pre2] #include <iostream> #include <iomanip> #include <memory> #include <iterator> #include <algorithm> #include <cstdlib> #include <ctime> int main() { size_t n, m; std::cout << "Enter the number of rows n = "; std::cin >> n; std::cout << "Enter the number of columns m = "; std::cin >> m; std::cout << '\n'; std::srand( ( unsigned int )std::time( nullptr ) ); int **a = new int *[n]; std::generate( a, a + n, [=] { return new int[m]; } ); std::for_each( a, a + n, [=]( auto row ) { std::generate( row, row + m, [=] { return std::rand() % ( n * m ); } ); } ); auto display_row = [=]( auto row ) { std::for_each( row, row + m, []( const auto &value ){ std::cout << std::setw( 2 ) << value << ' '; } ); std::cout << '\n'; }; std::for_each( a, a + n, display_row ); std::cout << '\n'; std::reverse( a, a + n ); std::for_each( a, a + n, display_row ); std::cout << '\n'; std::for_each( a, a + n, std::default_delete<int>() ); delete []a; } [/pre2] Вывод программы на консоль может выглядеть следующим образом: [pre2] Enter the number of rows n = 5 Enter the number of columns m = 5 19 1 12 21 23 8 11 24 24 2 6 9 12 11 18 3 8 21 5 24 2 10 17 23 7 2 10 17 23 7 3 8 21 5 24 6 9 12 11 18 8 11 24 24 2 19 1 12 21 23 [/pre2]
Ответов - 0
полная версия страницы