为什么我的2D阵列不能旋转?

时间:2018-03-20 22:37:15

标签: c++

我有一个平方的2D阵列,我想顺时针和逆时针旋转。

我在这里听到这个答案向右转:

Rotating a 2D pixel array by 90 degrees

我开发的代码:

void rotateRight()
{  
    for (int i = 0; i < m_width; i += 1) {
        for (int j = i + 1; j < m_height; j += 1) {
            std::swap(get(i, j), get(j, i));  
        }
    }
}

但是,阵列没有旋转。我有一个5x10的10x10阵列,在左上角是7.我希望7在旋转后转到右上角,但它仍然在左上角角。

成员函数get()是我自己的,只返回对单元格的引用。

T& get(const int x, const int y)
{ 
    return m_array[y * m_width + x];
} 

如何让它旋转?是否必须制作新阵列?很感激帮助。谢谢!

更新:

最新尝试。好的,所以&#39; 7&#39;最后从左上角到右上角向右旋转。但是当再次调用rotateRight()时,它会失败。我右上角的7号已经消失,不再找到。调查它。

for (int i = 0; i < m_width; i += 1) {
    for (int j = i + 1; j < m_height; j += 1) {
        get(j, i) = get(i, j);
    }
}
for (int i = 0; i < m_height; i++) {
    for (int j = 0, k = m_height - 1; j<k; j++, k--) {
        std::swap(get(j, i), get(k, i));
    }
}

输出:

Original:
700
000
000

Rotation #1:
J: 1, I: 0
J: 2, I: 0
J: 2, I: 1
J: 0, I: 0, K: 2
Value: 7 J: 0 K: 2
J: 0, I: 1, K: 2
Value: 0 J: 0 K: 2
J: 0, I: 2, K: 2
Value: 0 J: 0 K: 2
007
000
000

Rotation #2:
J: 1, I: 0
J: 2, I: 0
J: 2, I: 1
J: 0, I: 0, K: 2
Value: 0 J: 0 K: 2
J: 0, I: 1, K: 2
Value: 0 J: 0 K: 2
J: 0, I: 2, K: 2
Value: 0 J: 0 K: 2
000
000
000

最终代码

// Rotates a squared array clockwise.
void rotateRight()
{         
    T temp; 
    int halfwidth_floor = m_width / 2;
    int halfwidth_ceil = (m_width + 1) / 2; 

    for (int j = 0; j < halfwidth_floor; j += 1) {
        for (int i = 0; i < halfwidth_ceil; i += 1) {
            std::swap(temp, get(i, j)); 
            std::swap(get(i, j), get(j, m_width - i - 1));
            std::swap(get(j, m_width - i - 1), get(m_width - i - 1, m_width - j - 1));
            std::swap(get(m_width - i - 1, m_width - j - 1), get(m_width - j - 1, i));
            std::swap(get(m_width - j - 1, i), temp);
        }
    } 
}   

// Rotates a squared array counter-clockwise.
void rotateLeft()
{
    T temp; 
    int n = m_width;  

    for (int i = 0;  i < n / 2; i++) {
        for (int j = i; j < n - i - 1; j++) {
            std::swap(temp, get(i, j));  
            std::swap(get(i, j), get(n - j - 1, i));
            std::swap(get(n - j - 1, i), get(n - i - 1, n - j - 1));
            std::swap(get(n - i - 1, n - j - 1), get(j, n - i - 1));
            std::swap(get(j, n - i - 1), temp);
        }
    }
} 

2 个答案:

答案 0 :(得分:4)

内循环的每次迭代都是用(j,i)交换(i,j)。

如果(i == j),则它什么都不做。

如果(i!= j),那么交换将完成两次 - 例如,当i == 4且j == 3时,当i == 3和j == 4时完成交换。当然,做两次交换会导致整体没有发生任何事情。

这就是为什么你的代码将使用与它开始时完全相同的数组完成的原因。

您可能想要做的是将不同的数组写入您开始使用的数组。

编辑:没关系,我错过了问题的int j = i + 1部分,并认为两个循环都是从0迭代到宽度或高度。 (对于那些希望做同样事情的人来说,上述内容可能仍然是一个有用的见解。)

您的代码将转置,而不是旋转数组。 (转置意味着从左上角到右下角沿对角线反射。)要旋转,您需要将每个元素(i,j)移动到(j,w-i-1)或移动到(h-j-1,i)。 (当然,要旋转90度,你的阵列必须是一个正方形,即(w == h))。

编辑2:

如果你想在90度内就地旋转方阵,std :: swap将不起作用(因为它交换2个元素),原始赋值将不起作用(因为它丢失了信息)。但是,您可以做的是迭代四分之一的数组并旋转一系列4个元素,如下所示:

void rotateRight()
{
    int halfwidth_floor = m_width / 2;
    int halfwidth_ceil = (m_width + 1) / 2;
    for (int j = 0; j < halfwidth_floor; j += 1) {
        for (int i = 0; i < halfwidth_ceil; i += 1) {
            value_type temp = get(i, j);
            get(i, j) = get(j, m_width-i-1);
            get(j, m_width-i-1) = get(m_width-i-1, m_width-j-1);
            get(m_width-i-1, m_width-j-1) = get(m_width-j-1, i);
            get(m_width-j-1, i) = temp;
        }
    }
}

其中value_type是数组元素的类型(和m_width == m_height)。

在第一次迭代中,这会将左下角移动到左上角,然后右下角移动到左下角,然后右上角移动到右下角,然后是(暂时保存的)左上角到右上角。随后的迭代将对其他点进行相同的操作,越来越接近中心。请注意,一个for循环迭代到向下舍入的一半大小,另一个向上舍入:这是在具有奇数大小(例如5x5)的数组中,它将看到2x3的矩形及其“旋转” “在广场周围,避免将中间元素旋转两次(或根本不旋转)。

答案 1 :(得分:0)

你在做什么 转置矩阵。

你应该做什么 旋转矩阵的算法包括两个步骤

  1. 转置矩阵(如果向左旋转)。如果向右旋转,则转置并反转列的顺序
  2. 反转列
  3. 如下图所示

        1 2 3        1 4 7      3 6 9
        4 5 6    =>  2 5 8  =>  2 5 8
        7 8 9        3 6 9      1 4 7
    

    <强>代码 像这样,(初始化一个将保持旋转数组的辅助数组,因为形状可能不是正方形)

    void rotate()
    {  
        for (int i = 0; i < m_width; i += 1) {
            for (int j = i + 1; j < m_height; j += 1) {
                aux_array[j][i] = get(i, j)
            }
        }
        for (int i=0; i < m_height; i++) {
            for (int j=0,  int k=m_height-1; j<k; j++,k--) {
                swap(aux_array[j][i], aux_array[k][i]);
            }
        }
    }