Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++에서 1차원 배열로 2차원 배열 에뮬레이션하기: 행 우선·열 우선 변환 공식

C++ 프로그래밍에서 2차원 배열의 데이터를 1차원 배열에 저장하거나, 반대로 1차원 배열 하나만으로 2차원 배열처럼 다루어야 하는 경우가 자주 있습니다. 이 글에서는 2차원 배열의 요소를 1차원 배열에 올바르게 매핑하는 인덱스 변환 공식을 예제와 함께 자세히 살펴보겠습니다.

크기가 n×m인 2차원 배열의 전체 요소 개수는 n×m개이므로, 이를 담기 위한 1차원 배열의 크기도 동일하게 n×m으로 선언하면 됩니다.

2차원 배열을 1차원 배열로 저장하는 두 가지 방식

2차원 배열을 1차원 배열에 펼쳐 놓는(직렬화하는) 방법은 크게 두 가지가 있습니다.

  • 행 우선(Row-Major) 방식
  • 열 우선(Column-Major) 방식

1. 행 우선(Row-Major) 방식

행 우선 방식은 한 행(row)의 모든 요소를 차례대로 저장한 뒤, 다음 행으로 넘어가는 방법입니다. C, C++ 등 대부분의 프로그래밍 언어가 이 방식을 기본으로 사용합니다.

n×m 크기의 2차원 배열에서 인덱스 (i, j)에 있는 요소를 1차원 배열에 저장할 때의 위치는 다음과 같습니다.

1차원 인덱스 = (i × m) + j

2. 열 우선(Column-Major) 방식

열 우선 방식은 한 열(column)의 모든 요소를 먼저 저장하고, 그다음 열로 이동하는 방법입니다. Fortran이나 MATLAB처럼 수치 계산 중심의 언어에서 주로 쓰입니다.

같은 조건에서 인덱스 (i, j) 요소의 1차원 배열 위치는 다음과 같습니다.

1차원 인덱스 = (j × n) + i

예제로 이해하기

입력: n = 3(행), m = 5(열), 찾고자 하는 요소의 인덱스 (i, j) = (0, 2)

계산 과정:

행 우선(row-major) = (0 × 5) + 2 = 2
열 우선(column-major) = (2 × 3) + 0 = 6

즉, 같은 요소라도 어떤 방식으로 배치하느냐에 따라 1차원 배열에서의 위치가 달라진다는 것을 알 수 있습니다.

C++ 구현 코드

#include <iostream>
using namespace std;

int main() {
const int n = 3; // 행의 개수
const int m = 5; // 열의 개수

int grid[n][m] = {
{ 1, 2, 3, 4, 5},
{ 6, 7, 8, 9, 10},
{11, 12, 13, 14, 15}
};

int i = 0;
int j = 2;

// 행 우선(row-major) 인덱스 계산
int rowMajorIndex = i * m + j;
cout << "행 우선 방식에서 (0, 2) 요소의 1차원 배열 인덱스: " << rowMajorIndex << endl;

// 열 우선(column-major) 인덱스 계산
int colMajorIndex = j * n + i;
cout << "열 우선 방식에서 (0, 2) 요소의 1차원 배열 인덱스: " << colMajorIndex << endl;

return 0;
}

실행 결과

행 우선 방식에서 (0, 2) 요소의 1차원 배열 인덱스: 2
열 우선 방식에서 (0, 2) 요소의 1차원 배열 인덱스: 6

응용: 1차원 배열을 2차원 배열처럼 사용하기

반대로, 메모리 관리의 유연성을 위해 1차원 배열 하나만 선언해 두고 2차원 배열처럼 접근할 수도 있습니다. 이때도 앞서 살펴본 공식을 그대로 활용하면 됩니다.

#include <iostream>
using namespace std;

int main() {
const int n = 3, m = 5;
int arr[n * m]; // 1차원 배열만 선언

// 2차원처럼 값 저장: arr[i][j] 대신 arr[i * m + j] 사용
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
arr[i * m + j] = (i + 1) * (j + 1);

// (1, 3) 위치의 값 출력
cout << "arr[1][3]의 값: " << arr[1 * m + 3] << endl; // 8 출력

return 0;
}

마무리

2차원 배열과 1차원 배열 사이의 변환은 결국 인덱스 계산 공식 하나로 해결됩니다. 행 우선은 i × m + j, 열 우선은 j × n + i를 기억해 두면, 동적 할당이나 알고리즘 문제 풀이에서 1차원 배열만으로도 2차원 데이터를 자유롭게 다룰 수 있습니다.