表示为对象的一维向量时有效旋转NxM矩阵(C ++)

时间:2018-08-20 05:16:10

标签: c++ algorithm matrix linear-algebra

到目前为止,我想到的唯一方法是顺时针旋转NxM(N不一定等于M)矩阵(当它表示为一维向量,高度和宽度变量分开存储时) :

struct matrix
{
  vector<int> data;
  int height;
  int width;

  void rotate_90()
  {
    vector<int> newdata(height*width);
    for(int index = 0; index < height*width; index++)
    {
      int x = index % width;
      int y = index/width; // integer division
      int nextindex = (x+1)*height - 1 - y;
      newdata[nextindex] = data[index];
    }
    data = newdata;
    int temp = height;
    height = width;
    width = temp;
  }
};

虽然此方法确实有效,但我确信还有一种更为有效的方法(特别是在节省时间方面;空间不是问题)。必须创建一个全新的向量,然后用新的向量覆盖旧的向量,这对我来说感觉并不好。有没有更有效的解决方案?

请记住,我上面提供的只是为了说明。我实际代码中的data向量使用对象而不是整数;使用整数只是为了使其更易于测试。因此,像Eigen这样的线性代数库在这里无济于事。

1 个答案:

答案 0 :(得分:6)

如果可能,我会尽量避免完全复制数据,而仅在访问元素时才转换索引:

struct matrix {
  vector<int> data;
  int height;
  int width;

  int& at(int x,int y) { return data(x + y*width); }

  struct rotated_view {
    matrix& base;
    rotated_matrix_view(matrix& base) : base(base) {}
    int& at(int x,int y) { return base.at(y,base.height-x-1); }
  }

  rotated_view rotated() { return rotated_view(*this); }
};

请注意,根据您的访问方式,这可能会导致性能下降。另一方面,按列访问原始矩阵中的元素几乎与通过rotated_matrix_view按行访问它们的效率低下。如果您确实关心性能(当然可以,否则,为什么要使用C ++;)我建议您同时尝试一下索引转换和实际轮换,看看有什么更好的方法。