用C创建一个更有效的矩阵转置代码

时间:2014-02-11 23:54:11

标签: c pointers math transpose

我正在努力通过使用指针算法来创建这个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}}

我很擅长使用指针,所以任何建议/帮助都会非常感激。谢谢。

3 个答案:

答案 0 :(得分:1)

我最喜欢的诀窍就是不要动任何东西。

在您的结构中存储一个标志,表示您是按行还是按列访问,并更改您的get / set以尊重该标记。然后换位只是翻转那面旗帜。

答案 1 :(得分:0)

我建议从白板或干净的纸张开始。为你的内存指针绘制框,并绘制你的矩阵。从内存框中绘制箭头到指针引用的单元格位置。

一旦你这样做,你应该能够很容易地找到你的错误。

例如,如果您有以下代码:

int* row = A[i];

绘制带有行和列的A矩阵,然后绘制一个单独的框并将其标记为“行”。从框中绘制一个箭头到A [0]行,因为行将首先指向第0行。

使用指针和参考时总是有一个绘图表面!

答案 2 :(得分:0)

您的两个代码都存在一些问题。

第一个:

  • 正如drahnr所指出的那样,除了具有i == j的单元格之外,每个单元格都会发出两次交换。那些i == j的人根本没有交换,其他人交换两次,基本上什么也没做。

第二个:

  • t1变量完全未使用。
  • 你超越了数组为所有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];

也可以进行交换,无需承运人。我不知道它是否会优化这个过程,但是,只是一个有趣的技巧。