
본 시리즈는 프로그래밍 자료구조의 개념을 정리하고 실습을 진행해보는 시리즈입니다.

배열은 가장 기본적인 선형 자료구조로, 연속적인 메모리 공간에 동일한 타입의 데이터를 저장하는 구조입니다.
주요 특징:
O(1)입니다.list 자료형이 배열을 대신해서 동적으로 크기가 조절됩니다.배열의 빠른 연산 속도는 데이터가 연속적인 메모리 공간에 저장되기 때문에 가능해집니다.
x1000번지에 저장되었다면, 그 다음 요소는 메모리의 x1004번지에 저장됩니다. int)일 경우, 4바이트 크기의 메모리 공간을 차지하기 때문입니다.따라서 배열의 특정 인덱스에 접근하는 연산이 O(1)로 매우 빠른 이유는, 배열의 시작 주소와 인덱스를 이용해 직접 해당 요소의 메모리 주소를 계산할 수 있기 때문입니다.
배열의 시작 주소가 x1000번지라면, numbers[2]에 접근할 때의 메모리 주소는 1000 + (2 * 4) = x1008번지입니다.

이러한 메모리 효율성 덕분에 CPU 캐시를 효과적으로 활용할 수 있어, 데이터 처리 속도가 더 빨라집니다.
장점:
O(1)로 인덱스를 통한 데이터 접근이 매우 빠릅니다.단점:
O(n)의 시간이 걸리며, Java에서는 배열을 새로 만들어야 삽입/삭제를 할 수 있습니다.Java에서 배열은 고정 크기이며, 다음과 같이 선언하고 사용할 수 있습니다.
int[] numbers = new int[5]; // 크기가 5인 정수형 배열 선언
numbers[0] = 10; // 인덱스를 이용한 값 할당
System.out.println(numbers[0]); // 인덱스를 이용한 값 출력
배열의 크기는 선언 시 고정되므로, 크기를 변경하거나 중간에 값을 삽입/삭제하려면 새로운 배열을 생성해야 합니다.
Python에서는 list가 배열과 유사한 역할을 하지만, 고정 크기가 아니며 다양한 타입을 혼합할 수 있습니다. (고정된 크기의 배열을 기본적으로 제공하지 않습니다.)
numbers = [10, 20, 30, 40, 50] # 정수형 리스트 선언
print(numbers[0]) # 인덱스를 이용한 값 출력
Python의 리스트는 동적 배열처럼 작동하며, 크기를 유연하게 변경할 수 있습니다.
Java에서도 ArrayList와 같은 동적 배열 클래스를 사용할 수 있지만, 이 역시도 타입 지정이 필요하다는 점에서 Python과 큰 차이가 있습니다.
List를 다룰때 다시 다루도록 하겠습니다.배열에서 특정 인덱스에 있는 값을 조회하는 연산은 O(1)입니다.
Java
int value = numbers[2]; // O(1)
Python
value = numbers[2] # O(1)
배열의 끝에 새로운 데이터를 삽입하는 연산은 O(1)입니다.
하지만 중간에 삽입할 경우 모든 데이터를 이동해야 하므로 O(n)의 시간이 소요됩니다.
Java
// 배열의 크기는 고정이므로 중간 삽입을 위해 새로운 배열을 만들어야 함
Python
numbers.insert(2, 25) # 인덱스 2에 25 삽입 (O(n))
배열에서 데이터를 삭제하는 연산 역시 O(n)입니다.
삭제 후, 뒤에 있는 데이터들을 이동시켜야 하기 때문입니다.
Java
// Java에서는 배열 크기 고정이므로 직접 배열 이동 처리가 필요
Python
numbers.pop(2) # 인덱스 2에 있는 값 삭제 (O(n))
Java에서는 배열의 크기를 변경할 수 없기 때문에, 크기가 다른 배열을 만들고 데이터를 복사해야 할 경우가 많습니다.
Java
int[] newNumbers = new int[10];
System.arraycopy(numbers, 0, newNumbers, 0, numbers.length); // 배열 복사
Python
new_numbers = numbers.copy() # 리스트 복사
copy() 메서드를 사용하면 얕은 복사가 이루어집니다. copy.deepcopy()를 사용할 수 있습니다.배열의 정렬은 일반적으로 O(n log n) 복잡도를 가지며, Java는 Arrays.sort() 메서드, Python은 list.sort() 또는 sorted() 함수를 사용합니다.
Java
Arrays.sort(numbers); // 배열 정렬
Arrays.sort()는 기본형 타입 배열에 대해선 내부적으로 Dual-Pivot Quicksort를 사용하여 빠르게 정렬을 수행합니다. Quicksort는 평균적으로 O(n log n)의 성능을 보장하지만, 최악의 경우 O(n^2)이 될 수 있습니다.Python
numbers.sort() # 리스트 정렬
list.sort()는 Timsort 알고리즘을 사용하며, 이는 최악의 경우에도 O(n log n)을 보장합니다.자세한 정렬 알고리즘은 추후에 자세히 다룰 예정입니다.
문제: 배열에서 최대값 찾기
배열에서 최대값을 찾는 문제를 Java와 Python에서 각각 구현해보겠습니다.
public class Main {
public static void main(String[] args) {
int[] numbers = {10, 50, 30, 40, 20};
int max = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
}
System.out.println("최대값: " + max);
}
}
numbers = [10, 50, 30, 40, 20]
max_value = numbers[0]
for number in numbers[1:]:
if number > max_value:
max_value = number
print(f"최대값: {max_value}")
배열은 매우 기본적인 자료구조이지만, 그 특성과 동작 원리를 이해하는 것은 효율적인 알고리즘을 설계하는 데 필수적입니다.
다음 포스팅에서는 Java의 ArrayList와 Python의 List를 비교하며, 배열 기반 동적 자료구조에 대해 심도 있게 다뤄보겠습니다.
Array가 고정 크기인 반해서, 동적 배열인 Java ArrayList와 Python List는 크기를 유연하게 조절할 수 있는 특징을 가지고 있어, 이를 비교 분석해볼 것입니다.