【问题标题】:Map a 2D array onto a 1D array将二维数组映射到一维数组
【发布时间】:2011-01-10 04:48:56
【问题描述】:

我想用一维数组表示一个二维数组。一个函数将传递两个索引 (x,y) 和要存储的值。这两个索引将代表一维数组的单个元素,并相应地设置它。我知道一维数组需要有arrayWidth × arrayHeight的大小,但我不知道如何设置每个元素。

例如,如何区分 (2,4,3) 和 (4,2,3)?我尝试将数组设置为 x*y,但 2*4 和 4*2 会导致数组中的相同点,我需要它们不同。

【问题讨论】:

    标签: c arrays multidimensional-array


    【解决方案1】:

    您需要决定数组元素是以行顺序还是列顺序存储,然后保持一致。 http://en.wikipedia.org/wiki/Row-major_order

    C 语言对多维数组使用行顺序

    为了用一维数组模拟这个,你将行索引乘以宽度,然后添加列索引:

     int array[width * height];
    
     int SetElement(int row, int col, int value)
     {
        array[width * row + col] = value;  
     }
    

    【讨论】:

    • 我觉得这个答案比较清楚,尤其是初学者最好不要一行写函数...!!无论如何,这是不好的做法.. :)
    • 当您的编译器(例如嵌入式系统)没有适当的多维数组支持时,此答案也很有用
    • 令人惊讶的是,有多少人可以正确回答同一个问题,但只有一个人以易于理解的方式说出来。这是一个很简单的答案。然而,约翰是唯一一个真正为它提供一个好的答案的人。其余的都是垃圾,只有已经知道答案的人才能轻松理解。谢谢约翰,实际上是用英语而不是外星人说话。只是表明有些人在教学方面有多糟糕,以及像 John Knoeller 这样的优秀教师是如何比其他人更有效地简化和沟通的。
    • 如果一维数组的索引是alpha,并且二维数组在两个方向上的维度为N,索引为x, y,那么它会很好地展示如何反转这个映射:然后根据@JohnKnoeller,alpha=x+N*y。反转这种情况的方法是设置x=alpha%Ny= (alpha-alpha%N)/N
    • 我几乎每天都来这里!
    【解决方案2】:

    将二维数组索引重新计算为一维数组索引的典型公式是

    index = indexX * arrayWidth + indexY;
    

    你也可以使用

    index = indexY * arrayHeight + indexX;
    

    (假设arrayWidth沿X轴测量,arrayHeight沿Y轴测量)

    当然,可以想出许多不同的公式来提供替代的唯一映射,但通常没有必要。

    在 C/C++ 语言中,内置的多维数组存储在内存中,因此最后一个索引变化最快,这意味着对于声明为的数组

    int xy[10][10];
    

    元素xy[5][3] 紧跟在内存中的xy[5][4] 之后。您可能还想遵循该约定,根据您认为是两个公式中“最后一个”的索引(X 或 Y)选择上述两个公式之一。

    【讨论】:

      【解决方案3】:

      示例:我们想要表示一个 SIZE_X 和 SIZE_Y 大小的二维数组。这意味着我们将有 MAXY 个连续的 MAXX 行。因此集合函数是

      void set_array( int x, int y, int val ) { array[ x * SIZE_Y + y ] = val; }
      

      得到的是:

      int get_array( int x, int y ) { return array[ x * SIZE_Y + y ]; }
      

      【讨论】:

      • 您的MAXXMAXY 值的命名容易混淆,因为xy 的最大值分别为MAXX - 1MAXY - 1。也许SIZE_XSIZE_Y 会更好?
      • [y * maxx + x] 是列顺序,而不是行顺序。这是 matlab 的工作方式,但不是数组在 C 中的正常工作方式。
      • @everyone:除非你保持数据被触及,但纯粹是这两个 get/set 函数,并且它们使用相同的公式,你可以像这样或那样做。 (保证!)
      • 宏在这里可能更合适,因此您不会在应该是低级数据访问的情况下堆叠不必要的函数调用(特别是因为伪二维数组中的一维索引有时是优化技术。
      • 假设代码是类成员,这段代码将被内联。否则显式内联比宏好
      【解决方案4】:

      正如其他人所说的按行顺序排列的 C 映射

         #include <stdio.h>
      
         int main(int argc, char **argv) {
         int i, j, k;
         int arr[5][3];
         int *arr2 = (int*)arr;
      
             for (k=0; k<15; k++) {
                arr2[k] = k;
                printf("arr[%d] = %2d\n", k, arr2[k]);
             }
      
             for (i=0; i<5; i++) {
               for (j=0; j< 3; j++) {
                  printf("arr2[%d][%d] = %2d\n", i, j ,arr[i][j]);
               }
             } 
          } 
      

      输出:

      arr[0] =  0
      arr[1] =  1
      arr[2] =  2
      arr[3] =  3
      arr[4] =  4
      arr[5] =  5
      arr[6] =  6
      arr[7] =  7
      arr[8] =  8
      arr[9] =  9
      arr[10] = 10
      arr[11] = 11
      arr[12] = 12
      arr[13] = 13
      arr[14] = 14
      arr2[0][0] =  0
      arr2[0][1] =  1
      arr2[0][2] =  2
      arr2[1][0] =  3
      arr2[1][1] =  4
      arr2[1][2] =  5
      arr2[2][0] =  6
      arr2[2][1] =  7
      arr2[2][2] =  8
      arr2[3][0] =  9
      arr2[3][1] = 10
      arr2[3][2] = 11
      arr2[4][0] = 12
      arr2[4][1] = 13
      arr2[4][2] = 14
      

      【讨论】:

        【解决方案5】:

        使用行主要示例:

        A(i,j) = a[i + j*ld]; // where ld is the leading dimension
                              // (commonly same as array dimension in i)
        
        // matrix like notation using preprocessor hack, allows to hide indexing
        #define A(i,j) A[(i) + (j)*ld]
        
        double *A = ...;
        size_t ld = ...;
        A(i,j) = ...;
        ... = A(j,i);
        

        【讨论】:

          【解决方案6】:

          以可以使用所用语言检索数据的方式存储数据非常重要。 C 语言以行优先顺序存储(所有第一行都在前,然后是所有第二行,...),每个索引从 0 运行到它的维度 1。所以数组 x[2][3] 的顺序是 x[0][0], x[0][1], x[0][2], x[1][0], x[1][ 1],x[1][2]。因此在 C 语言中,x[i][j] 与一维数组项 x1dim[i*3 +j] 存储在相同的位置。如果数据是这样存储的,用C语言就很容易检索。

          Fortran 和 MATLAB 是不同的。它们以列优先顺序存储(所有第一列首先出现,然后是所有第二行,......)并且每个索引都从 1 运行到它的维度。所以索引顺序是 C 的倒数,所有索引都大 1。如果按 C 语言顺序存储数据,FORTRAN 可以使用 X_FORTRAN(j+1, i+1) 找到 X_C_language[i][j]。例如,X_C_language[1][2] 等于 X_FORTRAN(3,2)。在一维数组中,该数据值位于 X1dim_C_language[2*Cdim2 + 3],与 X1dim_FORTRAN(2*Fdim1 + 3 + 1) 的位置相同。请记住 Cdim2 = Fdim1,因为索引的顺序是相反的。

          MATLAB 与 FORTRAN 相同。除了索引通常从 1 开始之外,Ada 与 C 相同。任何语言都将具有这些 C 或 FORTRAN 顺序之一的索引,并且索引将从 0 或 1 开始,并且可以相应地进行调整以获取存储的数据。

          对不起,如果这个解释令人困惑,但我认为程序员知道它是准确且重要的。

          【讨论】:

            【解决方案7】:

            您应该能够使用简单的指针访问二维数组。数组[x][y] 将在指针中排列为 p[0x * width + 0y][0x * width + 1y]...[0x * width + n-1y][1x * width + 0y] 等.

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-11-22
              • 1970-01-01
              • 2014-09-03
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多