给定2D数组,转换为Z-Order

时间:2013-10-06 21:48:40

标签: c++ matrix multidimensional-array

无法绕过此次转化。我想递归地将2D NxN矩阵转换为其z阶版本。

例如给定数组:

[ 1  2 ]
[ 3  4 ]

Z顺序是

[ 1 2 3 4] 

z顺序转换的递归步骤是什么?

2 个答案:

答案 0 :(得分:2)

递归方式很简单:

  • 访问左上角
  • 访问右上角
  • 访问左下角
  • 访问右下角

代码

#include <iostream>

template<typename M, typename CBACK>
void zorder(const M& m, int y0, int x0, int size,
            CBACK cback)
{
    if (size == 1) {
        // Base case, just one cell
        cback(m[y0][x0]);
    } else {
        // Recurse in Z-order
        int h = size/2;
        zorder(m, y0,   x0,   h, cback); // top-left
        zorder(m, y0,   x0+h, h, cback); // top-right
        zorder(m, y0+h, x0,   h, cback); // bottom-left
        zorder(m, y0+h, x0+h, h, cback); // bottom-right
    }
}

void print(int x) {
    std::cout << x << " ";
}

int main(int argc, const char *argv[]) {
    int x[][4] = {{ 1,  2,  3,  4},
                  { 5,  6,  7,  8},
                  { 9, 10, 11, 12},
                  {13, 14, 15, 16}};
    zorder(x, 0, 0, 4, print);
    std::cout << std::endl;
    return 0;
}

此计划的输出

1 2 5 6 3 4 7 8 9 10 13 14 11 12 15 16

请注意,还有另一种非递归方法:以z顺序访问元素,您可以迭代计数器,将奇数位作为y,偶数位作为x(计算0位): / p>

int zorder_x_of(int index) {
    int x = 0;
    for (int b=0,k=0; (1<<b) <= index; b+=2,k++) {
        x += ((index & (1<<b)) != 0) << k;
    }
    return x;
}

int zorder_y_of(int index) {
    return zorder_x_of(index>>1);
}

template<typename M, typename CBACK>
void zorder2(const M& m, int size, CBACK cback)
{
    for (int i=0; i<size*size; i++) {
        cback(m[zorder_y_of(i)][zorder_x_of(i)]);
    }
}

注意:

在上面的代码示例中,我创建了一个接受“回调”(名为cback)的函数,该函数将使用矩阵的元素一次一个地按z顺序调用。

要允许同时使用矩阵和回调支持双[]索引的任何内容以及可以调用的任何内容,我使用了C ++模板。

在作为矩阵的主程序中,我使用了一个整数和函数的二维数组,但是代码甚至可以编译,例如以std::vector< std::vector< double > >作为矩阵和提供类的对象实例operator()(double)作为回调。

答案 1 :(得分:0)

2D矩阵在内部表现为1D阵列,即它已经处于“Z顺序”。

只需遍历指向第一个元素的指针,直到NxM,其中N是列数,M是行数。

示例:

int arr[2][2] = {{2,4},{3,5}};
for (int i=0; i<2 * 2; ++i){
    std::cout << *(&arr[0][0] + i);  // or *(arr + i)
}