我正在尝试将2D矩阵(10x10)换位:
for (a = 0; a < 10; a++) {
for (b = 0; b < 10; b++) {
tmp = matrix[a][b];
matrix[b][a] = matrix[a][b];
matrix[a][b] = tmp;
}
}
如果我可以将内部for语句的起始值'b'增加1
,则效果很好。
但是,当旋转一个循环时,变量的值将设置为0
。很自然。
是否有办法在循环运行后增加内部for
循环的起始值'b'?
我真的想解决这个问题。
您可以使用全局变量或任何其他方法来解决此问题吗?
答案 0 :(得分:4)
您的交换代码不正确:您应该先覆盖保存的值。
此外,您必须在b == a
时停止内部循环,否则值将被交换两次,并且换位将失败。
这是更正的版本:
/* swap values on either side of the first diagonal */
for (a = 1; a < 10; a++) {
/* stop the inner loop when b == a */
for (b = 0; b < a; b++) {
int tmp = matrix[a][b];
matrix[a][b] = matrix[b][a];
matrix[b][a] = tmp;
}
}
对于大型矩阵,特别是对于2阶幂,此简单算法并不是最佳的缓存。已经为in place matrix transpostion开发了更复杂的算法。
例如,这是1024x1024矩阵的基准,将朴素算法与高级递归方法进行了比较:
#include <stdio.h>
#include <time.h>
#define SIZE 1024
static int mat[SIZE][SIZE];
void initialize_matrix(int matrix[SIZE][SIZE]) {
int a, b, x = 0;
for (a = 0; a < SIZE; a++) {
for (b = 0; b < SIZE; b++) {
mat[a][b] = x++;
}
}
}
int check_transpose_matrix(int matrix[SIZE][SIZE]) {
int a, b, x = 0;
for (a = 0; a < SIZE; a++) {
for (b = 0; b < SIZE; b++) {
if (mat[b][a] != x++)
return 1;
}
}
return 0;
}
void naive_transpose(int matrix[SIZE][SIZE]) {
/* swap values on either side of the first diagonal */
for (int a = 1; a < SIZE; a++) {
/* stop the inner loop when b == a */
for (int b = 0; b < a; b++) {
int tmp = matrix[a][b];
matrix[a][b] = matrix[b][a];
matrix[b][a] = tmp;
}
}
}
#define THRESHOLD 4
void transpose_tile(int row, int col, int size, int matrix[SIZE][SIZE]) {
if (size > THRESHOLD) {
transpose_tile(row, col, size / 2, matrix);
transpose_tile(row, col + size / 2, size / 2, matrix);
transpose_tile(row + size / 2, col, size / 2, matrix);
transpose_tile(row + size / 2, col + size / 2, size / 2, matrix);
} else {
for (int a = 0; a < size; a++) {
for (int b = 0; b < size; b++) {
int tmp = matrix[row + a][col + b];
matrix[row + a][col + b] = matrix[col + b][row + a];
matrix[col + b][row + a] = tmp;
}
}
}
}
void transpose_tile_diag(int pos, int size, int matrix[SIZE][SIZE]) {
if (size > THRESHOLD) {
transpose_tile_diag(pos, size / 2, matrix);
transpose_tile(pos, pos + size / 2, size / 2, matrix);
transpose_tile_diag(pos + size / 2, size / 2, matrix);
} else {
/* swap values on either side of the first diagonal */
for (int a = 1; a < size; a++) {
/* stop the inner loop when b == a */
for (int b = 0; b < a; b++) {
int tmp = matrix[pos + a][pos + b];
matrix[pos + a][pos + b] = matrix[pos + b][pos + a];
matrix[pos + b][pos + a] = tmp;
}
}
}
}
void advanced_transpose(int matrix[SIZE][SIZE]) {
transpose_tile_diag(0, SIZE, matrix);
}
int main(int argc, char *argv[]) {
clock_t t_min;
initialize_matrix(mat);
naive_transpose(mat);
if (check_transpose_matrix(mat)) {
printf("naive_transpose failed!\n");
return 1;
}
/* benchmark naive algorithm */
t_min = 0;
for (int i = 0; i < 100; i++) {
clock_t t = clock();
naive_transpose(mat);
t = clock() - t;
if (i == 0 || t_min > t)
t_min = t;
}
printf("naive: %.3fms\n", t_min * 1000.0 / CLOCKS_PER_SEC);
initialize_matrix(mat);
advanced_transpose(mat);
if (check_transpose_matrix(mat)) {
printf("advanced_transpose failed!\n");
return 1;
}
/* benchmark advanced algorithm */
t_min = 0;
for (int i = 0; i < 100; i++) {
clock_t t = clock();
advanced_transpose(mat);
t = clock() - t;
if (i == 0 || t_min > t)
t_min = t;
}
printf("advanced: %.3fms\n", t_min * 1000.0 / CLOCKS_PER_SEC);
return 0;
}
我5岁的Macbook的输出:
naive: 7.299ms
advanced: 1.157ms