一尘不染

矩阵的原位转置

algorithm

(m,n)给定矩阵表示为单个大小数组,是否可以就地转置矩阵m*n

常用算法

transpose(Matrix mat,int rows, int cols ){
    //construction step
    Matrix tmat;
    for(int i=0;i<rows;i++){
      for(int j=0;j<cols;j++){
       tmat[j][i] = mat[i][j];
      }
    }
 }

除非矩阵是方形矩阵,否则不适用于单个数组。如果没有,则最少需要多少额外的内存?

编辑:我已经尝试了所有口味

for(int i=0;i<n;++i) {
  for(int j=0;j<i;++j) {
     var swap = m[i][j];
     m[i][j] = m[j][i];
     m[j][i] = swap;
  }
}

这是不正确的。在此特定示例中,m甚至不存在。在单行矩阵中mat[i][j] = mat[i*m + j]trans[j][i] = trans[i*n + j]


阅读 333

收藏
2020-07-28

共1个答案

一尘不染

受到Wikipedia的启发-在循环算法描述之后,我想到了以下C ++实现:

#include <iostream>  // std::cout
#include <iterator>  // std::ostream_iterator
#include <algorithm> // std::swap (until C++11)
#include <vector>

template<class RandomIterator>
void transpose(RandomIterator first, RandomIterator last, int m)
{
    const int mn1 = (last - first - 1);
    const int n   = (last - first) / m;
    std::vector<bool> visited(last - first);
    RandomIterator cycle = first;
    while (++cycle != last) {
        if (visited[cycle - first])
            continue;
        int a = cycle - first;
        do  {
            a = a == mn1 ? mn1 : (n * a) % mn1;
            std::swap(*(first + a), *cycle);
            visited[a] = true;
        } while ((first + a) != cycle);
    }
}

int main()
{
    int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
    transpose(a, a + 8, 4);
    std::copy(a, a + 8, std::ostream_iterator<int>(std::cout, " "));
}

该程序使2×4矩阵就地矩阵转置

0 1 2 3
4 5 6 7

行优先顺序表示 {0, 1, 2, 3, 4, 5, 6, 7}为4×2矩阵

0 4
1 5
2 6
3 7

由行优先的order表示{0, 4, 1, 5, 2, 6, 3, 7}

该参数mtranspose代表ROWSIZE,所述columnsize n由ROWSIZE和序列大小来确定。该算法需要辅助存储的m×
n位来存储信息,这些信息已被交换。序列的索引按以下方案映射:

0 → 0
1 → 2
2 → 4
3 → 6
4 → 1
5 → 3
6 → 5
7 → 7

映射功能通常是:

idx→(idx×n)mod(m×n-1)如果idx <(m×n),否则idx→idx

我们可以在这个序列中确定的四个周期:{ 0 }{ 1, 2, 4 }{3, 5, 6}{ 7 }。每个周期可以独立于其他周期进行转置。该变量cycle最初指向第二个元素(第一个元素不需要移动,因为0 → 0)。位数组visited保存已转置的元素,并指示索引1(第二个元素)需要移动。索引1与索引2交换(映射功能)。现在索引1持有索引2的元素,并且此元素与索引4的元素交换。现在索引1持有索引4的元素。索引4的元素应转到索引1,它在正确的位置,转置周期的结束,所有触摸的索引都已标记为已访问。变量cycle递增直到第一个未访问索引为3。该过程将继续该循环,直到所有循环都已转置为止。

2020-07-28