我正在努力通过使用指针算法来创建这个C代码的更高效版本但是我被卡住了。
这是原始代码:
(我正在调用我的数组类型Marray_t,int M)
void transpose(Marray_t A){
int i, j;
for(i=0; i<M; i++){
for(j=0; j<M; j++){
int t = A[i][j];
A[i][j] = A[j][i];
A[j][i] = t;
}
}
}
不使用malloc ,我想创建一种更有效的方法,在MxM维度的方阵上进行转置。
这就是我的尝试:
void transpose(Marray_t A, int M){
int i, j;
for (i=0; i<M; i++){
int *row = A[i];
for(j=0; j<M; j++){
int *col = &A[i][j];
int t1 = *(row+i);
int t2 = *(col + M*i)+(i*4);
*row = t2;
}
}
}
如果我在2x2矩阵上运行我的代码,它就不起作用。
如果我有矩阵= {{2,3},{4,5}},我的转置应该给我{{2,4},{3,5}},但我得到{{3,2} ,{4,5}}
我很擅长使用指针,所以任何建议/帮助都会非常感激。谢谢。
答案 0 :(得分:1)
我最喜欢的诀窍就是不要动任何东西。
在您的结构中存储一个标志,表示您是按行还是按列访问,并更改您的get / set以尊重该标记。然后换位只是翻转那面旗帜。
答案 1 :(得分:0)
我建议从白板或干净的纸张开始。为你的内存指针绘制框,并绘制你的矩阵。从内存框中绘制箭头到指针引用的单元格位置。
一旦你这样做,你应该能够很容易地找到你的错误。
例如,如果您有以下代码:
int* row = A[i];
绘制带有行和列的A矩阵,然后绘制一个单独的框并将其标记为“行”。从框中绘制一个箭头到A [0]行,因为行将首先指向第0行。
使用指针和参考时总是有一个绘图表面!
答案 2 :(得分:0)
您的两个代码都存在一些问题。
第一个:
i == j
的单元格之外,每个单元格都会发出两次交换。那些i == j
的人根本没有交换,其他人交换两次,基本上什么也没做。第二个:
2i >= M
覆盖的边界,访问了你应该搞乱的内存区域。查找
int t2 = *(col + M*i)+(i*4);
与:
完全相同int t2 = A[i + i][j] + (i*4);
第二个i
来自您的+ M*i
。用语言:
col
表示单元格[i][j]
,M * i
之后的单元格。M
单元格,将您带到下一列(或行,无论您想到哪种方式,都无关紧要)M * i
将意味着i
列/行进一步并且A[2i][j]
将超出M
不应超过的上限2i >= M
。
由于operator precedence,+ (i*4)
对正在使用的单元格没有任何影响。取消引用运算符*
在添加之前得到评估,要求您使用括号以防您希望添加更早发生;但在这种情况下,即使你使用它们,事情也不会好转。
这种方法无论如何都不会进一步优化过程。 Michael的方式很有趣,可能是最快的。但你可以修复第一个代码以正常工作(即不交换两次),也不要为i == j
发出交换,这应该足够好了。我不会告诉你如何做到这一点,你肯定能够做到。
我可以给你一个交换提示但是......而不是:
int t = A[i][j];
A[i][j] = A[j][i];
A[j][i] = t;
可以写:
A[i][j] ^= A[j][i];
A[j][i] ^= A[i][j];
A[i][j] ^= A[j][i];
也可以进行交换,无需承运人。我不知道它是否会优化这个过程,但是,只是一个有趣的技巧。