顺时针旋转 M*N 矩阵 90 度,C++

Rotate M*N matrix 90 Degrees Clockwise ,C++

本文关键字:C++ 矩阵 旋转 顺时针      更新时间:2023-10-16

我正在尝试旋转字符向量的向量。

我做了一个 2D 矢量矩阵设置。 现在矩阵从文件中获取输入, 我使用vector.push_back(c)将字符添加到 vvc; vvc 数组的一个例子是这样的

aaaaa
azzza
azaza
azzza
azaaa
azaaa
azaaa
aaaaa

我有 vvc 设置,但我正在尝试将其旋转 90 度。我逆时针旋转了 90 度,但我需要顺时针旋转 90 度。

截至目前,我的代码这样做

90 counter clock
aaaaaaaa
azzzzzza
azazaaaa
azzzaaaa
aaaaaaaa

它通过这个循环来做到这一点;

cout <<"n90 counter clock"<<endl;
for (size_t colNo = 0; colNo < kvsize2; colNo++)
{
for (const auto &row : twovector)
{
char colVal = row.at(colNo);
cout << colVal;
}
cout << endl;
}

我只是在学习向量和范围。尝试做一个递减循环几乎有效,但总是让我陷入段错误。

"已解决">我正在使用

twovector.push_back(temp);

twovector.insert(twovector.begin(),temp);

给我

90 counter clock aaaaaaaa azzzzzza aaaazaza aaaazzza aaaaaaaa

处理问题的特定部分:

如果有人对如何旋转 M*N 2d 矢量数组有任何提示或建议

C++擅长将算法与数据隔离。

请注意,答案有点长,并且是为了教程的目的而编写的。
让我们开始吧!!

我们希望从我们的rotate_2d_matrix_clockwise算法中获得 3 个功能:

  • 它应该适用于所有数据类型,即intchardouble或任何用户定义的类型。
  • 它应该适用于不同类型的容器,例如std::arraystd::vector
  • 它应该是可链的,即用户应该能够调用rotate_2d_matrix_clockwiserotate_2d_matrix_clockwise返回的结果,以实现2次旋转。

一旦我们明确了我们的要求,我们就可以为我们的算法起草一些用例。

std::vector<std::vector<char>> data = { {'a', 'b', 'c', 'd'}, 
{'e', 'f', 'g', 'h'}, 
{'i', 'j', 'k', 'l'} };
rotate_2d_matrix_clockwise(data); // rotating 2d-matrix of vector<char>
std::array<std::array<int, 4>, 3> data2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
// rotating 2d-matrix of array<int>, twice
rotate_2d_matrix_clockwise(rotate_2d_matrix_clockwise(data2))); 

因此,让我们使用一些模板来创建通用的 2D 顺时针旋转函数。

我们的rotate_2d_matrix_clockwise将:

  • original_matrix并返回一个新的rotated_matrix
  • 自动推断尺寸,即传递给它的容器的M x N
  • 创建rotated_matrix并将其传递给帮助程序函数,rotate_2d_matrix_clockwise_impl实际工作将在其中完成。

那么std::arrayrotate_2d_matrix_clockwise的实施会是什么样子呢?

template<typename T, size_t M, size_t N>
auto rotate_2d_matrix_clockwise(std::array<std::array<T, M>, N> const & original_matrix)
-> std::array<std::array<T, N>, M>
{
std::array<std::array<T, N>, M> rotated_matrix;
rotate_2d_matrix_clockwise_impl(original_matrix, rotated_matrix, M, N); // rotate
return rotated_matrix;
}

整洁而精确。
不过,std::vectorrotate_2d_matrix_clockwise实现有点混乱。

template<typename Matrix2D>
auto rotate_2d_matrix_clockwise(Matrix2D const & original_matrix) -> Matrix2D
{
int const M = original_matrix[0].size(); // deduce M and N
int const N = original_matrix.size();
Matrix2D rotated_matrix; // vector has no form, hence we have to resize it for `N x M`
rotated_matrix.resize(M);
for (auto x = 0; x < M; ++x) {
rotated_matrix[x].resize(N);
}
rotate_2d_matrix_clockwise_impl(original_matrix, rotated_matrix, M, N); // rotate
return rotated_matrix;
}

现在让我们看看实际的旋转算法rotate_2d_matrix_clockwise_impl会是什么样子。
应该注意的是,该算法独立于容器和/或包含的数据。它只专注于旋转。

template<typename OriginalMatrix2D, typename RotatedMatrix2D>
void rotate_2d_matrix_clockwise_impl(OriginalMatrix2D const & original_matrix,
RotatedMatrix2D        & rotated_matrix,
int              const M,
int              const N)
{
for (auto x = 0; x < N; ++x) {
for (auto y = 0; y < M; ++y) {
// Source : https://stackoverflow.com/questions/4780119/2d-euclidean-vector-rotations
rotated_matrix[y][-x -1 +N] = original_matrix[x][y];
}
}
}

这是在 C++11 中编译的完整工作示例。

#include <iostream>
#include <vector>
#include <array>
template<typename Matrix2D>
void print_matrix(Matrix2D const & vec)
{
std::cout << "size of matrix is [" << vec[0].size() << " x " << vec.size() << "]n";
for (auto const & inner_vec : vec) {
for (auto const & item : inner_vec) {
std::cout << item << ", ";
}
std::cout << std::endl;
}
}
template<typename OriginalMatrix2D, typename RotatedMatrix2D>
void rotate_2d_matrix_clockwise_impl(OriginalMatrix2D const & matrix,
RotatedMatrix2D        & rotated_matrix,
int              const M,
int              const N)
{
for (auto x = 0; x < N; ++x) {
for (auto y = 0; y < M; ++y) {
// Source : https://stackoverflow.com/questions/4780119/2d-euclidean-vector-rotations
rotated_matrix[y][-x -1 +N] = matrix[x][y];
}
}
}
template<typename T, size_t M, size_t N>
auto rotate_2d_matrix_clockwise(std::array<std::array<T, M>, N> const & original_matrix)
-> std::array<std::array<T, N>, M>
{
std::array<std::array<T, N>, M> rotated_matrix;
rotate_2d_matrix_clockwise_impl(original_matrix, rotated_matrix, M, N);
return rotated_matrix;
}
template<typename Matrix2D>
auto rotate_2d_matrix_clockwise(Matrix2D const & original_matrix) -> Matrix2D
{
int const M = original_matrix[0].size();
int const N = original_matrix.size();
Matrix2D rotated_matrix;
rotated_matrix.resize(M);
for (auto x = 0; x < M; ++x) {
rotated_matrix[x].resize(N);
}
rotate_2d_matrix_clockwise_impl(original_matrix, rotated_matrix, M, N);
return rotated_matrix;
}

int main()
{
std::array<std::array<int, 4>, 3> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
std::cout << "nBefore Rotation :n";
print_matrix(data);
std::cout << "nAfter 2nd Clockwise Rotation :n";
print_matrix(rotate_2d_matrix_clockwise(rotate_2d_matrix_clockwise(data)));
std::vector<std::vector<char>> data2 = { {'a', 'b', 'c', 'd'}, {'e', 'f', 'g', 'h'}, {'i', 'j', 'k', 'l'}};
std::cout << "Before Rotation :n";
print_matrix(data2);
std::cout << "nAfter Clockwise Rotation :n";
print_matrix(rotate_2d_matrix_clockwise(data2));
return 0;
}

如果我做对了,你想要的只是顺时针打印矩阵 90 度,试试这个代码:

for (int colNo = 0; colNo < vec[0].size(); colNo++)
{
for (int i = vec.size() - 1; i >= 0; i--)
{
const auto& row = vec[i];
int colVal = row.at(colNo);
cout << colVal;
}
cout << endl;
}