C++ 原地旋转二维矩形阵列

C++ 原地旋转二维矩形阵列,c++,arrays,rotation,in-place,C++,Arrays,Rotation,In Place,我有一个非方形数组,如下所示: const int dim1 = 3, dim2 = 4; int array[12] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12}; 我需要将其转换为: {3,6,9,12, 2,5,8,11, 1,4,7,10} 也就是说,逆时针旋转/洗牌(或者顺时针,算法应该类似) 算法应该使用最小的空间量。我必须在内存非常

我有一个非方形数组,如下所示:

const int dim1 = 3, dim2 = 4;
int array[12] = { 1, 2, 3, 
                  4, 5, 6,
                  7, 8, 9,
                 10,11,12};
我需要将其转换为:

{3,6,9,12,
 2,5,8,11,
 1,4,7,10}
也就是说,逆时针旋转/洗牌(或者顺时针,算法应该类似)


算法应该使用最小的空间量。我必须在内存非常有限的环境中旋转图像,因此空间越小越好。速度不是一个大问题。

您可以使用xor来使用附加内存

// Switch a and b
int a;
int b;
a ^= b;
b ^= a;
a ^= b;

然后,您可以使用一个简单的
for
循环来生成整个矩阵。

您可以在适当的位置转置矩阵(请参阅),然后反转不重要的行。

二维旋转公式为:

x' = x cos f - y sin f
y' = y cos f + x sin f
如果仅以90°的步长旋转,则生成的公式为:

x' = -y
y' =  x
由于数组不是正方形,您必须查找赋值周期,即元素(0,0)得到赋值元素(2,0),而元素(2,0)又得到赋值元素(2,2),等等。您需要在“相同”的时间分配每个周期

因此,要旋转整个数组,您将执行以下操作(伪代码):

//此函数可旋转90度
点继任者(常数点和p)
{
回报率(-p.y,p.x);
}
//此功能以相反方向旋转90度
点前置器(常数点和p)
{
回报率(同比,-p.x);
}
无效替换循环(恒定点和开始)
{
int data=get_data(开始);
点x=前置(开始);
while(x!=开始)
{
设置_数据(后继(x),获取_数据(x));
x=前置(x);
}
设置_数据(后继(开始),数据);
}
在_位置()中旋转
{
清单l;
求_循环(l);
foreach(c在l中)
{
更换_循环(c);
}
}

完全不旋转可能是一种选择。您只需设置一个标志,该标志将给出读取矩阵的方式


缺点是,如果必须将该图像提供给某个显示设备或具有固定方向的显示设备,这可能是不可能的。

旋转是否总是以90°的步长进行?我想您在这里回答的是不同的问题。@wilx:请再次阅读该问题,将阵列旋转到位!除非你理解问题和答案,否则请不要投反对票。@wilx:同意,我最初的尝试可能有点幼稚,但它的帮助不亚于描述xor交换的答案,而且它肯定不是我回答的另一个问题。看起来这对平方矩阵很有效,但是(据我所见)不适用于非平方矩阵。它的大小为[12]。它在记忆中不是二维的。只有解释。恐怕你唯一的选择就是要么翻译fortran源代码,要么阅读论文,从头开始实现它。请注意,您为原始问题找到的任何算法都意味着一个众所周知的矩阵转置问题的解决方案。在遍历表时,还存在缓存局部性惩罚。之前,逐行遍历是有效的,之后它将意味着看似随机的读取。@Matthieu M。如果您是逐行遍历表,这是正确的,但我们没有这方面的信息。奥普还明确表示,他更关心的是空间而不是速度。我知道,但这在某种程度上是需要考虑的。大多数时候,我并不太在意性能,除非它使我的软件无法使用,也就是:-)@Matthieu M:在这种情况下,不使用正确的内存访问确实会降低几个数量级的速度。
// this function rotates 90 degrees
point successor(const point &p)
{
  return (-p.y, p.x);
}

// this function rotates 90 degrees in opposite direction
point predecessor(const point &p)
{
  return (p.y, -p.x);
}

void replace_cycle(const point &start)
{
  int data = get_data(start);
  point x = predecessor(start);
  while(x != start)
  {
    set_data(successor(x), get_data(x));
    x = predecessor(x);
  }
  set_data(successor(start), data);
}

void rotate_in_place()
{
  list<point> l;
  find_cycles(l);
  foreach(c in l)
  {
    replace_cycle(c);
  }
}