我在想找到矩阵转置的方法,下面是算法,但它没有给我正确的输出,所以任何人都可以告诉我我在哪里犯了错误,以及什么应该是正确的算法?我该如何改进它?
// m is the number of rows and n is the number of columns in a matrix
for (int i = 0; i < m; i++) // For swapping the non-diagonal elements
{
for (int j = 0; j < n; j++)
{
if (i != j)
{
int temp = 0;
temp = a[i][j];
a[i][j] = a[j][i];
a[j][i] = temp;
}
}
}
cout << "Elements of transpose matrix of a is: " << endl;
for (int i = 0; i < m; i++) // printing the elements after transpose
{
for (int j = 0; j < n; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
Run Code Online (Sandbox Code Playgroud)
您在反转一维数组时犯了同样的错误,因此我将使用它作为一个更简单的示例:
#include <vector>
#include <iostream>
#include <utility>
std::vector<int> reverse_broken(std::vector<int> x){
for (size_t i=0;i< x.size(); ++i){
std::swap(x[i],x[x.size()-1-i]);
}
return x;
}
int main(){
auto x = reverse_broken({1,2,3,4});
for (const auto& e : x) std::cout << e << " ";
}
Run Code Online (Sandbox Code Playgroud)
输出:
1 2 3 4
Run Code Online (Sandbox Code Playgroud)
reverse_broken迭代所有元素并将它们与相应的反转元素交换。然而,一旦第一个与最后一个交换,最后一个就已经被交换了。随后将最后一个与第一个交换,使它们再次按原始顺序排列。
与你的转置相同。一旦将对角线上方的元素与对角线下方的元素交换,它们就已经转置了。您无需再次交换它们。
我将向您展示修复方法,reverse_broken并让您对转置应用相同的修复:
std::vector<int> reverse(std::vector<int> x){
for (size_t i=0;i< x.size()/2; ++i){
// stop in the middle ^^ because then all elements have been swapped
std::swap(x[i],x[x.size()-1-i]);
}
return x;
}
Run Code Online (Sandbox Code Playgroud)
您还应该考虑根本不转置矩阵。根据您访问交换元素的频率以及填充它的方式,从一开始就按正确的顺序填充它,或者只是在访问时交换索引会更便宜:
// normal access:
auto x = a[i][j];
// transposed access:
auto y = a[j][i];
Run Code Online (Sandbox Code Playgroud)
PS:我reverse仅用于说明。要反转容器,您实际上应该使用std::reverse. 另请注意,您可以而且应该使用std::swap. 最后但并非最不重要的一点是,只有方阵可以就地转置。对于非方阵,您需要构造一个具有不同维度的新矩阵。