使用C++转置矩阵

4

我想编写一个程序来转置一个n*n矩阵,但是代码输出了一些奇怪的东西。它没有转置矩阵。假设我想要转置一个矩阵{(1,2,3), {4,5,6),(7,8,9)},结果与原始矩阵基本相同,但存在一些我不知道的奇怪行为。

#include<iostream>
#include<iomanip>
using namespace std;
void transpose(int* p, int n);
#define M 20
int main()
{
    int a[M][M];
    int n;      
    int* p;
    cout << "The size of a matrix is: ";
    cin >> n;
    cout << "Input a matrix: " << endl;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> a[i][j];
    p = &a[0][0];
    transpose(p, n);
    cout << "Now, the matrix is: " << endl;
    for (int i = 0; i < n; i++)
    {

        for (int j = 0; j < n; j++)
        {
            cout << setw(4) << a[i][j];
        }
        cout << endl;
    }
    return 0;
}

void transpose(int* p, int n)
{
    for (int i = 0; i < n; i++)
    {
        for (int j = i; j < n; j++)
        {
            int temp = *(p + i * n + j);
            *(p + i * n + j) = *(p + j * n + i);
            *(p + j * n + i) = temp;
        }
    }
}

这里我看不到任何C++代码。我只看到C代码。如果这是C++代码,我会期望看到std::vector,而不是普通的二维数组。 - Sam Varshavchik
@SamVarshavchik 这不是有效的 C 代码,但它是有效的 C++ 代码。 - ryanpattison
3
@SamVarshavchik 关于 cout、endl、<< 运算符。虽然这些元素可能没有充分利用一些有用的 C++ 标准库组件,但它们绝不是 C 语言。 - andand
1个回答

4
你应该调用:
transpose(p, M);

替代方案:

transpose(p, n);

虽然你的矩阵是 3x3,但你为一个 20x20 的矩阵保留了内存。所以下一行距离上一行有 20int(两行之间的内存间隔称为步幅)。

为了加快进程,你可以实现一个三参数版本:

void transpose(int* p, int m, int n) {
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            int temp = *(p + i * m + j);
            *(p + i * m + j) = *(p + j * m + i);
            *(p + j * m + i) = temp;
        }
    }
}

并使用以下方式进行调用:

transpose(p, M, n);

但是,老实说,我认为您在内存中定义矩阵的方式以及转置算法可以得到改进。您的transpose方法并不真正适合缓存。为了快速计算,我建议使用LAPACK包。这种算法以块为单位工作,可以显著减少缓存故障数量,并且还利用多线程进行提升性能。请查看此讲座,获取有关如何高效转置矩阵的更多详细信息。


换句话说,transpose() 中使用的“步幅”是错误的。三参数 transpose() 是一个好的解决方案;更好的解决方案是一开始只存储 n * n 个值。 - John Zwinck
@JohnZwinck:请查看更新的答案,但说实话,最好使用一个包,我们部门的许多研究人员为这些包做出了重要贡献,设计了针对密集/稀疏矩阵的算法,这些算法经过了极度优化。自己编写的算法击败它们的机会非常小。 - Willem Van Onsem
感谢您的详细解释,谢谢大家。 - Jun Liu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接