Reputation: 19
I am looking for the best algorithm to do a rotation of a row in a 2D array / matrix. Let's say we have
mat[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
I want to shift the element to the left by one, the first row 1 2 3
will then become 2 3 1
. The function realizes this by copying each element to the left via dynamical memory allocation.
void rotate_row(const int& row) {
int *temp_row = (int *) (malloc(3));
for (int i = 0; i < 3; ++i) {
temp_row[i % 3] = mat[row][(i + 1) % 3];
}
memcpy(mat[row], temp_row, 3);
free(temp_row);
}
To manipulate any specific row, we simple call the function rotate_row(row)
.
I don't quite understand malloc thing in C, since I grow up learning a completely new way of dynamical allocation, so I first change it to:
void rotate_rows(const int& row) {
//int *temp_row = (int *) (malloc(3));
int *temp_row = new int[3];
for (int i = 0; i < 3; ++i) {
temp_row[i % 3] = mat[row][(i + 1) % 3];
}
memcpy( mat[row], temp_row, 3);
//free(temp_row);
delete [] temp_row;
temp_row = NULL;
}
My question first is, will simply changing the way of dynamical memory allocation accelerates the code?
Also, I don't think it is necessary to use dynamical memory allocation for my purpose(rotate the row). Is their any better (not necessary the best) algorithm available?
Upvotes: 0
Views: 1467
Reputation: 543
Yes there's a better way and no need to use dynamic memory allocation. You actually don't need another array to solve this. Here's a sample code:
for(int i = 0; i < n/2; i++){
for(int j = i; j < n-i-1; j++){
int tmp = matrix[i][j];
matrix[i][j] = matrix[n-j-1][i];
matrix[n-j-1][i] = matrix[n-i-1][n-j-1];
matrix[n-i-1][n-j-1] = matrix[j][n-i-1];
matrix[j][n-i-1] = tmp;
}
}
This is pretty straight forward so I think you'll understand the code easily without explanation.
Upvotes: 0
Reputation: 35440
You can avoid all the dynamic memory allocation, and use the std::rotate algorithm:
#include <algorithm>
#include <iostream>
int main()
{
int mat[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
// rotate left each row by 1
for (int i = 0; i < 3; ++i)
std::rotate(&mat[i][0], &mat[i][1], &mat[i][3]);
for (int i = 0; i < 3; ++i)
std::cout << mat[i][0] << " " << mat[i][1] << " " << mat[i][2] << "\n";
}
Output:
2 3 1
5 6 4
8 9 7
Edit:
Here is a sample of rotating each row by it's row index + 1:
#include <algorithm>
#include <iostream>
int main()
{
int mat[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
// rotate left each row by 1
for (int i = 0; i < 3; ++i)
std::rotate(&mat[i][0], &mat[i][i+1], &mat[i][3]);
for (int i = 0; i < 3; ++i)
std::cout << mat[i][0] << " " << mat[i][1] << " " << mat[i][2] << "\n";
}
Output:
2 3 1
6 4 5
7 8 9
Upvotes: 1
Reputation: 2385
Rotating will not change array size, hence doing it in-place sounds much more performant to me, no need for dynamic memory allocation and freeing previous pointer.
void rotate(int * array, size_t n) {
if (n <= 1)
return;
const int head = array[0];
for (size_t i = 1; i < n; ++i)
array[i - 1] = array[i];
array[n - 1] = head;
}
Upvotes: 1