배열 자료구조 정리

Date:     Updated:

Categories:

Tags:

동적 배열

dynamic array 라고 하며, 원소를 추가하면서 자동으로 크기가 2배씩 늘어나는 형태의 배열


정적 배열

크기가 고정되어있는 배열

int arr[4];


성능

접근

정적 배열, 동적 배열 모두 인덱스를 이용한 접근은 O(1) 가 소요된다.

왜그럴까?

배열의 대표적인 특징인 순차적 저장 때문이라고 볼 수 있다.

같은 선형 자료구조인 연결리스트와 비교했을때 가장 큰 차이점이, 연결리스트는 메모리 곳곳에 저장되어있는 반면, 배열은 메모리 상으로 순차적으로 저장 되어있는 것이다.

바로 이 특징 때문에 우리가 arr[3] 을 하면 O(1) 로 원소에 접근 할 수 있는 것이다.

예를 들어 arr 이라는 배열에 원소가 4개 (1,2,3,4) 있다고 치자.

int 는 크기가 4 바이트 이기 때문에 다음과 같은 형태로 저장될것이다.

1000 = 1
1004 = 2
1008 = 3
1012 = 4

이때 a = arr[3] 를 하면 왜 선형 시간 으로 접근이 가능한걸까?

단순 수학이라고 생각해도 될것 같다.

C 언어에서는 배열 자체가 어디 저장 되어있는지 확인해보면 첫번째 원소의 주소가 나오는것을 확인할 수 있을것이다.

즉, arr 의 주소랑 arr[0] 주소가 같은 것이다.

이 특징을 이용하면 인덱스로 접근하는것도 쉽다.

arr의 주소 + sizeof(원소) x i(인덱스)

를 하면 우리가 찾고자 하는 인덱스가 바로 나오기 때문이다.

즉, 우리가 찾고있던 인덱스는 3이기 때문에

arr의 주소(1000) + sizeof(int) x i(3) 주소에 있는 원소를 꺼내올 수 있다.


삽입/삭제

배열은 기본적으로 삽입/삭제 모두 O(N) 이 소요된다고 볼 수 있다.

단, 동적 배열의 가장 끝에 원소를 추가할때는 평균적으로 O(1) 이 소요되고 최악의 경우에만 O(N) 이 소요된다.

O(1) 이 나올 수 있는 이유는 바로 분할상환분석(amortized analysis) 때문이다.


분할상환분석(amortized analysis)

N 크기의 배열이 있다고 해보자.

그러면 N 크기가 될때까지, 배열의 크기가 두배로 커지고, 그때 원소들을 전부 복사해야되는 시점이 언제인지 분석해보자.

마지막 시점부터 거꾸로 생각을해보면 편하다.

우선 직전에 두배로 커졌을때는 N/2 개의 원소를 복사했을것이고.

그 전에는 N/4 , 그전에는 N/8 ..1이 될때까지 계속 반으로 주는 것을 볼 수 있다.

그걸 나열해보면

N/2 + N/4 + N/8 + N/16 + ... + 2 + 1

이런식으로 될 것이다.

이걸 다 더해비면 N 이 조금 안되는 것을 알 수 있다.

결론적으로 말하면, N 개의 원소를 삽입할때 총 O(N) 정도가 소요되는데, 각각의 삽입 자체는 O(1) 이 소요된다.

datastructures 카테고리 내 다른 글 보러가기

첫 번째 글입니다 가장 최근 글입니다