转置部可以做这样的:
#include <stdio.h>
typedef struct Sequence2D
{
int idx_slow;
int idx_fast;
int max_slow;
int max_fast;
} Sequence2D;
static inline void next2D(Sequence2D *seq)
{
if (++seq->idx_fast == seq->max_fast)
{
seq->idx_fast = 0;
if (++seq->idx_slow == seq->max_slow)
seq->idx_slow = 0;
}
}
static inline void dump2D(const char *tag, int rows, int cols, int data[rows][cols])
{
printf("%s:\n", tag);
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
printf("%3d", data[r][c]);
putchar('\n');
}
}
enum { ROWS = 3, COLS = 7 };
int main(void)
{
int src[ROWS][COLS] =
{
{ 1, 2, 3, 4, 5, 6, 7 },
{ 8, 9, 10, 11, 12, 13, 14 },
{ 15, 16, 17, 18, 19, 20, 21 },
};
int dst[ROWS][COLS];
Sequence2D dst2D = { 0, 0, COLS, ROWS };
Sequence2D src2D = { 0, 0, ROWS, COLS };
dump2D("Source", ROWS, COLS, src);
for (int i = 0; i < ROWS * COLS; i++)
{
dst[dst2D.idx_fast][dst2D.idx_slow] = src[src2D.idx_slow][src2D.idx_fast];
printf("dst[%d][%d] = src[%d][%d] = %d\n",
dst2D.idx_fast, dst2D.idx_slow,
src2D.idx_slow, src2D.idx_fast,
dst[dst2D.idx_fast][dst2D.idx_slow]);
next2D(&dst2D);
next2D(&src2D);
}
dump2D("Target", ROWS, COLS, dst);
return 0;
}
的Sequence2D
结构加上通过数组索引next2D()
函数周期,改变上的next2D()
每个呼叫和慢指数在必要时快速指数。这可以节省您编写21个任务的顺序,并立即缩放到其他形状,而不需要您做额外的工作。实际上,将所有大小作为运行时输入而不是编译时常量处理并不多。
这段代码的输出是:
Source:
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
dst[0][0] = src[0][0] = 1
dst[1][0] = src[0][1] = 2
dst[2][0] = src[0][2] = 3
dst[0][1] = src[0][3] = 4
dst[1][1] = src[0][4] = 5
dst[2][1] = src[0][5] = 6
dst[0][2] = src[0][6] = 7
dst[1][2] = src[1][0] = 8
dst[2][2] = src[1][1] = 9
dst[0][3] = src[1][2] = 10
dst[1][3] = src[1][3] = 11
dst[2][3] = src[1][4] = 12
dst[0][4] = src[1][5] = 13
dst[1][4] = src[1][6] = 14
dst[2][4] = src[2][0] = 15
dst[0][5] = src[2][1] = 16
dst[1][5] = src[2][2] = 17
dst[2][5] = src[2][3] = 18
dst[0][6] = src[2][4] = 19
dst[1][6] = src[2][5] = 20
dst[2][6] = src[2][6] = 21
Target:
1 4 7 10 13 16 19
2 5 8 11 14 17 20
3 6 9 12 15 18 21
如果您根据您复制的src
“转”到结果之前,你使用任何晦涩难懂的规则重新排列初始矩阵(src
)(dst
),那么你应该能够得到你想要的结果。
如上所述,代码可以相当容易地使用C99和可变长度数组广义:
#include <assert.h>
#include <stdio.h>
typedef struct Sequence2D
{
int idx_slow;
int idx_fast;
int max_slow;
int max_fast;
} Sequence2D;
static inline void next2D(Sequence2D *seq)
{
if (++seq->idx_fast == seq->max_fast)
{
seq->idx_fast = 0;
if (++seq->idx_slow == seq->max_slow)
seq->idx_slow = 0;
}
}
static inline void dump2D(const char *tag, int rows, int cols, int data[rows][cols])
{
printf("%s:\n", tag);
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
printf("%3d", data[r][c]);
putchar('\n');
}
}
static void transpose(int rows, int cols)
{
assert(rows * cols < 1000000);
int src[rows][cols];
int dst[rows][cols];
Sequence2D dst2D = { 0, 0, cols, rows };
Sequence2D src2D = { 0, 0, rows, cols };
int cells = rows * cols;
for (int i = 0; i < cells; i++)
{
src[src2D.idx_slow][src2D.idx_fast] = i;
next2D(&src2D);
}
/* src2D is back to its initial state! */
dump2D("Source", rows, cols, src);
for (int i = 0; i < cells; i++)
{
dst[dst2D.idx_fast][dst2D.idx_slow] = src[src2D.idx_slow][src2D.idx_fast];
printf("dst[%d][%d] = src[%d][%d] = %d\n",
dst2D.idx_fast, dst2D.idx_slow,
src2D.idx_slow, src2D.idx_fast,
dst[dst2D.idx_fast][dst2D.idx_slow]);
next2D(&dst2D);
next2D(&src2D);
}
dump2D("Target", rows, cols, dst);
}
int main(void)
{
transpose(3, 7);
transpose(9, 4);
return 0;
}
输出的第一部分是以前一样; 9x4部分看起来像:
Source:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
16 17 18 19
20 21 22 23
24 25 26 27
28 29 30 31
32 33 34 35
dst[0][0] = src[0][0] = 0
dst[1][0] = src[0][1] = 1
dst[2][0] = src[0][2] = 2
dst[3][0] = src[0][3] = 3
dst[4][0] = src[1][0] = 4
dst[5][0] = src[1][1] = 5
dst[6][0] = src[1][2] = 6
dst[7][0] = src[1][3] = 7
dst[8][0] = src[2][0] = 8
dst[0][1] = src[2][1] = 9
dst[1][1] = src[2][2] = 10
dst[2][1] = src[2][3] = 11
dst[3][1] = src[3][0] = 12
dst[4][1] = src[3][1] = 13
dst[5][1] = src[3][2] = 14
dst[6][1] = src[3][3] = 15
dst[7][1] = src[4][0] = 16
dst[8][1] = src[4][1] = 17
dst[0][2] = src[4][2] = 18
dst[1][2] = src[4][3] = 19
dst[2][2] = src[5][0] = 20
dst[3][2] = src[5][1] = 21
dst[4][2] = src[5][2] = 22
dst[5][2] = src[5][3] = 23
dst[6][2] = src[6][0] = 24
dst[7][2] = src[6][1] = 25
dst[8][2] = src[6][2] = 26
dst[0][3] = src[6][3] = 27
dst[1][3] = src[7][0] = 28
dst[2][3] = src[7][1] = 29
dst[3][3] = src[7][2] = 30
dst[4][3] = src[7][3] = 31
dst[5][3] = src[8][0] = 32
dst[6][3] = src[8][1] = 33
dst[7][3] = src[8][2] = 34
dst[8][3] = src[8][3] = 35
Target:
0 9 18 27
1 10 19 28
2 11 20 29
3 12 21 30
4 13 22 31
5 14 23 32
6 15 24 33
7 16 25 34
8 17 26 35
为什么你想这样洗牌?你想达到什么目的? – dbush
洗牌背后的逻辑并不直观。它应该如何工作? –
你只是想随机重新分配它们吗? – Makogan