2D 배열을 1D 배열에 매핑


92

1D 배열로 2D 배열을 표현하고 싶습니다. 함수는 두 개의 인덱스 (x, y)와 저장할 값을 전달합니다. 이 두 인덱스는 1D 배열의 단일 요소를 나타내며 그에 따라 설정합니다. 1D 배열에 arrayWidth × arrayHeight 크기가 필요하다는 것을 알고 있지만 각 요소를 설정하는 방법을 모르겠습니다.

예를 들어, (2,4,3)과 (4,2,3)을 어떻게 구별합니까? 배열을 x * y로 설정하려고했지만 2 * 4 및 4 * 2는 배열에서 동일한 지점을 생성하므로 서로 달라야합니다.

답변:


167

배열 요소를 행 순서 또는 열 순서로 저장할지 여부를 결정한 다음 일관성을 유지해야합니다. http://en.wikipedia.org/wiki/Row-major_order

C 언어는 다차원 배열에 행 순서를 사용합니다.

1 차원 배열로이를 시뮬레이션하려면 행 인덱스에 너비를 곱하고 열 인덱스를 추가합니다.

 int array[width * height];

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

7
이 답변이 더 명확하다고 생각합니다. 특히 초보자에게는 한 줄에 함수를 작성하지 않는 것이 좋습니다 ... !! 어쨌든 나쁜 습관입니다 .. :)
Lipis

3
이 답변은 적절한 다차원 배열 지원이없는 컴파일러 (예 : 임베디드 시스템)를 사용할 때도 유용합니다.
Alex Marshall

1
얼마나 많은 사람들이 같은 질문에 정확하게 답할 수 있는지 놀랍습니다.하지만 그들 중 한 사람 만이 이해하기 쉬운 방식으로 대답합니다. 이것은 대답이 얻는 것처럼 간단합니다. 그러나 John은 실제로 그것에 대한 좋은 대답을 제공하는 유일한 사람입니다. 나머지는 이미 답을 알고있는 사람들 만 쉽게 이해할 수있는 쓰레기입니다. 실제로 외계인 대신 영어로 말하는 John에게 감사합니다. 일부 사람들이 가르치는 데 얼마나 나쁜지, 그리고 John Knoeller와 같은 훌륭한 교사가 다른 모든 사람들보다 훨씬 더 효과적으로 단순화하고 의사 소통하는 방법을 알고 있는지 보여줍니다.
user2948630

6
1 차원 배열의 인덱스 인 경우 :이 매핑을 반전하는 방법을 보여 좋은 것 alpha, 그리고 2 차원 배열은 차원이 N인덱스와 양방향을 x, y, 다음 @JohnKnoeller에 따라 alpha=x+N*y. 이를 반전하는 방법은 설정 x=alpha%Ny= (alpha-alpha%N)/N.
Tim

나는 거의 매일 여기에옵니다!
Felipe Gutierrez

23

2D 배열 인덱스를 1D 배열 인덱스로 재 계산하는 일반적인 공식은 다음과 같습니다.

index = indexX * arrayWidth + indexY;

또는 사용할 수 있습니다

index = indexY * arrayHeight + indexX;

( arrayWidthX 축 arrayHeight과 Y 축을 따라 측정 되었다고 가정 )

물론 대체 고유 매핑을 제공하는 다양한 공식을 생각 해낼 수 있지만 일반적으로 그럴 필요는 없습니다.

C / C ++ 언어에서 내장 된 다차원 배열은 메모리에 저장되므로 마지막 인덱스가 가장 빠르게 변경됩니다. 즉, 다음과 같이 선언 된 배열의 경우

int xy[10][10];

요소 xy[5][3]xy[5][4]메모리에서 바로 뒤에옵니다 . 두 가지 중 "마지막"으로 간주하는 인덱스 (X 또는 Y)에 따라 위의 두 공식 중 하나를 선택하여이 규칙을 따를 수도 있습니다.


17

예 : SIZE_X 및 SIZE_Y 크기의 2D 배열을 나타내려고합니다. 즉, MAXX 크기의 연속 된 행을 MAXY 개 갖게됩니다. 따라서 설정된 기능은

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 ]; }

1
귀하 MAXXMAXY최대의 값 때문에 값이 혼동, 명명 x하고 y있습니다 MAXX - 1MAXY - 1각각. 아마도 SIZE_XSIZE_Y더 좋을 수도?
카페

3
[y * maxx + x]는 행 순서가 아니라 열 순서입니다. 이 MATLAB의 작동 방식이지만, 일반적으로 C에서 작동하지 않는 방식으로 배열이다
존 Knoeller

@everyone : 데이터를 그대로 유지하지만 순전히이 두 가지 가져 오기 / 설정 함수가 동일한 공식을 사용하지 않는 한 THIS 또는 그와 같이 할 수 있습니다. (보장!)
imacake 2011

여기에 매크로가 더 적합 할 수 있으므로 저수준 데이터 액세스로 간주되는 항목에 대해 불필요한 함수 호출을 쌓지 않습니다 (특히 의사 2d 배열의 1d 인덱싱이 때때로 최적화 기술
이기 때문에)

코드가 클래스 멤버라고 가정하면이 코드는 인라인됩니다. 그렇지 않으면 명시 적 인라인이 매크로보다 훨씬 낫습니다.
Kornel Kisielewicz 2014 년

7

다른 사람들이 말했듯이 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

3

행 주요 예제 사용 :

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);

1

사용 된 언어로 검색 할 수있는 방식으로 데이터를 저장하는 것이 중요합니다. 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]는 1 차원 배열 항목 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)과 같습니다. 1 차원 배열에서 해당 데이터 값은 X1dim_C_language [2 * Cdim2 + 3]에 있으며, 이는 X1dim_FORTRAN (2 * Fdim1 + 3 + 1)과 동일한 위치입니다. 인덱스의 순서가 반대이므로 Cdim2 = Fdim1임을 기억하십시오.

MATLAB은 FORTRAN과 동일합니다. Ada는 인덱스가 일반적으로 1에서 시작하는 것을 제외하고 C와 동일합니다. 모든 언어는 해당 C 또는 FORTRAN 주문 중 하나의 인덱스를 가지며 인덱스는 0 또는 1에서 시작하며 저장된 데이터를 얻기 위해 그에 따라 조정할 수 있습니다.

이 설명이 혼란 스럽다면 미안하지만 프로그래머가 아는 것이 정확하고 중요하다고 생각합니다.


-2

간단한 포인터를 사용하여 2D 배열에 액세스 할 수 있어야합니다. 배열 [x] [y]는 포인터에 p [0x * 너비 + 0y] [0x * 너비 + 1y] ... [0x * 너비 + n-1y] [1x * 너비 + 0y] 등으로 배열됩니다. .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.