배열의 확장된 개념 (배열보다 편한 기능들을 제공)
배열을 활용해서 구현하는 것이 가장 적합 (링크드 리스트로도 구현은 가능)
벡터와 배열의 관계 : 배열 + 여러 함수 = 클래스화 ⇒ 벡터
주소가 아닌 index로 배열의 element를 access 한다.
탐색, 삽입, 삭제 모두 index 로 한다.
incorrect index 호출시 exception 발생 (ex) 인덱스 -3 의 element 조회)
at(integer i) : 인덱스 i에 있는 element 를 리턴 => return V[i]
set(integer i, object o) : 인덱스 i의 element를 새로운 값 o로 대체
insert(integer i, object o) : 인덱스 i에 o를 삽입
erase(integer i) : 인덱스 i에 있는 element 제거.
( 크기가 N인 배열 A을 사용하는 것을 가정. N과 n은 다르다. n은 배열안에 담겨있는 현재 element의 개수, N은 배열의 크기 )
사용 공간 : O(N)
size, empty, at, set : O(1)
insert, erase : O(n) (최악의 경우)
환형배열로 구현한다면, insert(0, x)와 erase(0) 처럼 0번 인덱스에 대한 삽입, 삭제만 필요한 경우 O(1) 에 수행가능
배열이 가득찼을 때 insert 하는 경우 : O(1) - 더블링으로 구현시에만
그냥 평소에 insert 하는 경우 : O(n)
⇒ insert 연산 수행시 마지막 원소의 인덱스가
"벡터에 내부적으로 사용하고 있던 배열의 크기 -1" 보다 크다면, 즉 insert 하려는데 배열이 꽉차있으면 배열을 새로 할당하게 된다.
cf. 당연하게도 새로 할당받았으므로 할당받은 배열의 주소는 기존 배열 주소와 다름!
Growable Array-based Vector 에서 아래와 같은 insert 연산은
배열이 꽉 찼을시에 insert시 O(n), 아직 꽉 안찼을 때 insert시엔 O(1) 이 걸린다. ( 꽉 찼을때는 배열을 카피 해야하므로 O(n) ). 그러나 더블링 strategy 로 구현하면 배열이 꽉찼을때 insert연산 O(1)이 걸리게 된다.
아래 수도코드는 배열의 맨 끝에다 삽입하는 insert 함수임을 가정한다.
// 배열 끝에다 삽입
// 기존 배열 S를 새로운 배열 A에 할당
// S:배열이름, A:새로 할당한 배열, S.length : 배열 원소의 개수(배열의 크기가 아니다!) <->(S.size: 배열의 크기)
// t : 배열의 마지막 인덱스 번호, N : 배열의
Algorithm insert(o) // insert(N,o) 구현할 수도 있지만, 배열 끝에다 삽입한다는 것을 알고 있으므로, 또 인덱스 N에다 삽입하는 것인지 모를수도 있으므로 insert(o) 로 구현함
if t = S.length - 1 then // full (배열이 꽉찬 경우). => 여담이지만, n = S.size() 으로 해도될듯?
A <- new array of // 새로운 배열 A 생성
size <- ... // 사이즈는 구현하기 나름임. 당연한거지만 기존 배열 사이즈인 n보다는 커야할 것임 (* 구현 방법은 Incremental / Doubling 구현법 2가지이다 )
for i <- 0 to n-1 do // 최악의 경우 => 이 for문 때문에 insert 연산이 O(n) 이 걸린다. (즉, 기존 배열을 카피해야 해서 O(n) 이 걸림)
A[i] <- S[i] // 새로운 배열 A에 기존 배열 S의 값들을 할당
S <- A // 기존 S의 주소값을 A의 주소값으로 바꿔버리면, A가 새로운 S가 된다.
// 아래 2문장은 다음 2문장으로 구현해도됨. S[n] <- 0 n <- n + 1
n <- n + 1
S[n-1] = o
Incremental strategy : O(n)의 수행시간이 걸림
Doubling strategy : Amortized 분석 결과 O(1)의 수행시간이 걸림
=> 더블링 방법이 더 효율적이다. ( STL vector 가 사용하는 방법 )
상식적으로 생각하면 입력크기가 많아질수록 더블링을 할 필요가 점점 없어지므로
안정적으로 작동이 가능해서, 더블링이 잘 안일어난다는 것!
→ 지금 우리 레벨로 이해할 수 없으므로 그냥 그렇구나 생각하기 ^^
ex) 사이즈가 40인 꽉찬 배열에 insert하면 80이 된다.
여기서 erase를 한다고 바로 사이즈가 40으로 돌아오지 않는다.
사이즈 값인 80의 1/4 인 20이 되면 그때 사이즈를 절반인 40으로 줄인다.
공간: O(N)
insert
erase
at
set
empty
size