C++에서 배열의 특정 인덱스 요소 제거와 오프셋 변수의 역할

배열에서 여러 요소를 제거하고 남은 요소들을 새로운 배열에 올바르게 재배치하는 작업은 C++ 프로그래밍에서 자주 발생하는 메모리 조작 문제입니다. 예를 들어, 다음과 같은 동적 배열이 있다고 가정합시다:

int* original = new int[10]{3, 5, 1, 11, 99, 66, 22, 2, 8, 6};

여기서 인덱스 0과 5에 위치한 값(각각 3과 66)을 제거하고, 나머지 8개의 요소로 구성된 새 배열을 생성해야 한다면 어떻게 해야 할까요? 아래는 이를 구현하는 방법과 핵심 개념인 오프셋(offset)의 의미를 설명합니다.

알고리즘 설계

동적 배열에서 특정 인덱스의 요소를 제거하려면 다음 단계를 따릅니다:

  1. 제거 후 남을 요소 수만큼의 새 배열을 동적 할당합니다 (이 경우 10 - 2 = 8).
  2. 기존 배열을 순회하면서, 제거 대상이 아닌 요소만 새 배열에 복사합니다.
  3. 복사 과정에서 인덱스 불일치를 보정하기 위해 오프셋 값을 사용합니다.
  4. 기존 배열의 메모리를 해제하고, 필요 시 포인터를 새 배열로 재할당합니다.

코드 구현 및 분석

#include <iostream>
using namespace std;

int main() {
    // 원본 배열 생성
    int* original = new int[10]{3, 5, 1, 11, 99, 66, 22, 2, 8, 6};

    // 두 개의 요소 제거 → 새 배열 크기는 8
    int* result = new int[8];

    // 오프셋 초기화: 건너뛴 요소 수를 기록
    int skipCount = 0;

    for (int idx = 0; idx < 10; ++idx) {
        // 인덱스 0 또는 5인 경우 건너뜀
        if (idx == 0 || idx == 5) {
            skipCount++;  // 건너뛴 횟수 증가
            continue;
        }

        // 현재 요소를 새 배열의 올바른 위치에 저장
        result[idx - skipCount] = original[idx];
    }

    // 이전 배열 메모리 해제
    delete[] original;

    // 포인터 재할당 (선택 사항)
    original = result;

    // 결과 출력
    for (int i = 0; i < 8; ++i) {
        cout << result[i] << endl;
    }

    return 0;
}

오프셋(skipCount)의 역할

skipCount 변수는 제거된 요소의 누적 개수를 추적합니다. 기존 배열의 인덱스 idx를 사용할 때, 실제로 새 배열에 저장될 위치는 idx - skipCount입니다. 이는 다음과 같은 이유에서 중요합니다:

  • 인덱스 0에서 첫 번째 요소가 제거되면, 이후 모든 요소는 왼쪽으로 한 칸씩 당겨져야 합니다.
  • 두 번째 제거(인덱스 5)에서는 이미 1칸의 오프셋이 존재하므로, 그 뒤 요소들은 총 2칸 앞당겨집니다.
  • 예: 원래 인덱스 6에 있던 값 22는 6 - 2 = 4 위치에 저장됩니다.

이러한 방식은 조건부로 요소를 건너뛸 때도 정확한 위치 계산을 보장하며, 추가적인 임시 저장소 없이 선형 시간 내에 처리할 수 있습니다.

출력 결과

위 코드를 실행하면 다음과 같은 출력이 나타납니다:

5
1
11
99
22
2
8
6

원본 배열에서 인덱스 0(값 3)과 인덱스 5(값 66)가 성공적으로 제거되었으며, 나머지 요소들이 순서를 유지한 채 새 배열에 저장된 것을 확인할 수 있습니다.

메모리 관리 주의사항

  • new[]로 할당한 메모리는 반드시 delete[]로 해제해야 합니다.
  • 포인터 재할당 후에도 여전히 유효한 참조를 유지하도록 주의해야 하며, 중복 해제나 메모리 누수가 발생하지 않도록 해야 합니다.

태그: C++ 배열 조작 동적 메모리 할당 오프셋 포인터

9월 13일 12:17에 게시됨