[C++] 이터레이터와 STL
LastMod:
👨💻 개인 공부 기록용 블로그 입니다.
💡 틀린 내용이나 오타는 댓글, 메일로 제보해주시면 감사하겠습니다!! (__)
42 Cursus - Cpp Module을 진행하기 위해 정리했었던 C++98 기본 개념들로, C++11, C++14와 다른 내용이 있을 수 있습니다.
각 개념은 정리한 시간 순으로 배치되어 있으며, 한 포스트에 배치된 개념이 크게 관련이 없을 수 있습니다.
이터레이터 (Iterator)
💡 지시자, 반복자와 같이 번역하는 경우도 많이 보았는데, 어감이 이상하기도 하고, 본래의 의미를 잘 못살린다는 생각이 들어서 그냥 이터레이터로 적기로 했다. C++의 이터레이터에 대해서만 기술한다.
- 이터레이터 (Iterator) 는 C++의 다양한 구조에서 균일한 방식으로 작업할 수 있도록 도와주는 포인터의 일반화된 형태이다.
Input Iterator
- 컨테이너로부터 데이터를 순차적으로 읽기 위한 이터레이터
++it(이터레이터 증가연산),*it(이터레이터 참조),==,!=(두 이터레이터가 같은지 비교 하는 연산) 등이 이에 속한다.- 스트림으로부터 데이터를 읽거나, 범위에 대해 한 번만 수행하면 되는 연산에 쓰인다.
Output Iterator
- 데이터를 순차적으로 쓰는 출력 작업에 사용되는 이터레이터
*it = something(쓰기 위한 이터레이터 참조),it++(이터레이터 증가연산) 등이 이에 속한다.- 스트림에 데이터를 쓰거나, 컨테이너 맨 뒤에 원소를 삽입하는 연산에 쓰인다.
Forward Iterator
- Input Iterator + Output Iterator
- 순차적인 데이터 읽기 쓰기 작업에 사용됨
Bidirectional Iterator
- Forward Iterator + 역방향 연산
- 양방향으로 데이터 읽기 쓰기가 가능함. →
--it(이터레이터 감소연산) 가능 - 양방향 연결리스트와 같이 일정 범위 내 양방향 순회가 가능함
- list, set, map이 양방향 이터레이터를 지원함 → 이터레이터 끼리의 산술 연산(덧셈, 뺼셈)이 불가능함.
Random Access Iterator
- Bidirectional Iterator + 이터레이터에 대한 산술 연산
- 덧셈 뺄셈과 같은 산술 연산에 더불어, 상대적인 비교연산 (
<,>,<=,>=) 가능 - 원소 랜덤 접근이 가능한 컨테이너(vector, array)는 모두 지원
Writing Custom Iterators
- 컨테이너 클래스 내부에 이터레이터 클래스를 추가적으로 정의 및 구현
- 구현하고자 하는 이터레이터의 카테고리를 결정한 후, 그에 맞는 연산자 오버로딩 구현 (
*,++,--,==,!=등) - 랜덤 접근 이터레이터의 경우에는
+,-,[]연산도 구현해야 함. - 필수 사항은 아니지만,
begin(),end()또한 구현하면 좋다. const_iterator,reverse_iterator,const_reverse_iterator도 재구현한다.
STL (Standard Template Library)
- 표준 템플릿 라이브러리 STL (Standard Template Library) 은 템플릿을 통해 구현되어 프로그래머로 하여금 기본적인 자료구조들을 추가 구현없이 사용할 수 있게 만든 라이브러리
- 크게 세 종류 (컨테이너와 알고리즘, 이터레이터)로 구분된다.
- 컨테이너 : 임의 타입의 객체 보관
- 이터레이터 : 컨테이너에 보관된 원소에 접근
- 알고리즘 : 이터레이터를 통한 일련의 작업 수행
- 이터레이터 같은 경우는 위에 서술. 컨테이너는 종류별로 구분하여 대표적인 것을 서술하고, 알고리즘은 자주 사용될 법 한 것만 따로 정리
- C++11 버전에서 유효한 것은 바탕색을 회색으로 처리함.
Containers
Sequence Container
Vector: 연속적인 동적 배열- 배열의 크기와 관련된 메모리 관리를 사용자가 아닌 배열 스스로 관리
- 연속적인 메모리 공간에 고정된 크기를 우선 할당한 뒤, 필요할 경우 추가 할당함.
- C++에서는 메모리 할당/해제 연산이 비싼 축에 속하기 때문에, 파이썬 처럼 원소를 제거한 후 일부 메모리를 해제하는 연산은 이뤄지지 않고, 오직 소멸자가 호출될 때만 메모리를 해제함.
- 연속적인 메모리를 사용하기 때문에 사용성에 있어서 효율적이지만, 덱과 비교하여 재할당이 자주 일어남
- 끝단에서의 삽입 및 삭제와 원소 랜덤 접근은 \( O(1) \)에 이뤄지지만, 특정 위치에서의 삽입 및 삭제는 \( O(N) \)이 소요됨
- vector
의 경우, 메모리 공간을 최적화하기 위하여 템플릿 특수화를 통해 구현됨. - 자주 쓰이는 멤버 함수 :
push_back,pop_back,insert,erase,size,capacity,reserve
Deque: 양 끝에서 삽입/제거가 가능한 큐- 벡터와 비슷하지만, 양 끝단에서의 삽입/제거 연산에 좀 더 최적화된 자료구조
- 벡터와 같이 \( O(1) \)에 랜덤 접근이 가능하며, 같은 시간에 양 끝단에서의 삽입/제거가 가능함.
- chunks 단위로 메모리를 할당하여 관리하기 때문에, 벡터보다는 일반적으로 메모리를 더 사용함.
- 자주 쓰이는 멤버 함수 :
push_back,push_front,pop_back,pop_front,insert,erase,size
List: 양방향 연결 리스트- 어디서든 삽입/제거 연산을 효율적으로 수행하기 위한 자료구조
- 인덱스를 통한 원소 랜덤 접근이 불가능하다. 반드시 순차적으로 접근해야만 한다.
- 재할당 및 복사 없이 크기를 동적으로 조절할 수 있다.
- 원소와 이전 원소에 대한 포인터, 다음 원소에 대한 포인터를 함께 저장하기 때문에, 어디서든 삽입 제거가 효율적이지만 일반적으로 더 많은 메모리를 사용한다.
- 자주 쓰이는 멤버함수 :
push_back,push_front,pop_back,pop_front,insert,erase,size
Array- 벡터와 달리, 컴파일 타임에 크기가 고정되는 배열
- 힙 메모리가 아닌 스택에 할당되기 때문에 빠르며, \( O(1) \)에 랜덤 접근이 가능하다.
- 자주 쓰이는 멤버함수 :
begin,end,size,fill,swap
Forward_list- list와 달리, 단방향 연결 리스트를 통해 구현됨
- 어디서든 삽입/제거 연산을 효율적으로 수행할 수 있음.
- list의 특징을 대부분 가지지만, 양방향 이터레이터를 지원하지 않으며, 더 좋은 메모리 효율성을 가짐.
- 자주 쓰이는 멤버변수 :
insert_after,erase_after,push_front,pop_front,push_back,pop_back
Associative Container
Set:key로 정렬되는 유니크한key들의 집합- 원소들이 항상
key를 기준으로 오름차순 정렬되어 있음 - 중복되는 원소들을 담을 수 없으며, 크기가 동적으로 관리됨.
- \( O(logN) \)에 삽입/삭제/탐색이 가능함.
- 자주 사용되는 멤버함수 :
insert,erase,find,count,begin,end,size
- 원소들이 항상
Map: 유니크한key로 정렬되는key-value쌍의 집합- 원소들이
key-value쌍의 형태를 띄고 있으며, 항상key에 대해 오름차순 정렬됨 - 중복되는
key를 담을 수 없으며, 크기가 동적으로 관리됨. - \( O(logN) \)에 삽입/삭제/탐색이 가능함.
- 자주 사용되는 멤버함수 :
insert,erase,find,count,begin,end,size
- 원소들이
Mulitset:set과 유사하지만, 다중key를 허용함Mulitmap:map과 유사하지만, 다중key-value쌍(중복되는key)을 허용함
Unordered Associative Container
- 아래는 모두 C++11에서 소개된 자료구조로, 연관 컨테이너와 비슷하지만 내부적으로 정렬을 수행하지 않음.
- 그러나 해시테이블을 통해 빠른 접근이 가능하도록 함.
Unordered_setset과 비슷한 특징을 갖지만, 정렬을 수행하지 않고 해싱(hashing)을 통해 원소를 관리함.- 원소 삽입/접근/삭제에 대해 평균 \( O(1) \)의 복잡도로 수행 가능함. 해싱의 특성 상, 최악의 경우 \( O(N) \)까지 소요될 수 있음.
- 자주 쓰이는 멤버 함수 :
insert,erase,find,begin,end,size
Unordered_mapmap과 비슷한 특징을 갖지만, 정렬을 수행하지 않고 해싱(hashing)을 통해 원소를 관리함.- 원소 삽입/접근/삭제에 대해 평균 \( O(1) \)의 복잡도로 수행 가능함. 해싱의 특성 상, 최악의 경우 \( O(N) \)까지 소요될 수 있음.
- 자주 쓰이는 멤버 함수 :
insert,erase,find,begin,end,size
Unordered_multiset:Unordered_set과 유사하지만, 다중key를 허용함Unordered_multimap:Unordered_map과 유사하지만, 다중key-value쌍(중복되는key)을 허용함
Container Adapter
- Sequential 컨테이너에 대해 다른 인터페이스를 제공. 데이터 구조를 가지지 않고, 다른 컨테이너를 통해 원소를 저장함.
Stack: 컨테이너가 스택 구조를 띄도록 조정- LIFO(Last In, First Out)구조를 띔.
- 최상단에서만 접근/추가/삭제가 가능하며, 기본적으로
deque를 사용함. 물론list나vector를 사용하는 것도 가능함. - 자주 사용되는 멤버함수 :
push,pop,top,size,empty
Queue: 컨테이너가 큐 구조를 띄도록 조정- FIFO(First In, First Out)구조를 띔.
- 양 끝단에서만 접근/추가/삭제가 가능하며, 기본적으로
deque를 사용함.list또한 사용 가능함. - 자주 사용되는 멤버함수 :
push,pop,front,back,size,empty
Priority_queue: 컨테이너가 우선순위 큐 구조를 띄도록 조정- 원소들이 삽입 순서가 아닌 우선순위에 따라 정렬되어 있음.
- 가장 우선순위가 높은 원소에만 접근이 가능함.
- 기본적으로
vector를 사용하며,deque또한 사용 가능함. - 우선순위 설정을 위한 비교 함수 사용자화를 할 수 있음
- 자주 쓰이는 멤버함수 :
push,pop,top,size,empty
Algorithms
- 컨테이너의 이터레이터를 인자로 받아서 처리하며, 원소 검색, 정렬, 계산, 조작 등 다양한 목적을 위한 다양한 함수가 포함된 알고리즘 라이브러리
Non-modifying Sequence Operations
- 컨테이너의 원소들을 변경하지 않는 연산들
**find(first, last, value)**:[first, last)에 대해value를 탐색**count(first, last, value)**:[first, last)에 대해value의 개수를 세는 함수**mismatch(first1, last1, first2)**:[first1, last1)과[first2, first2 + (last1 - first1))두 범위를 비교하여 첫 번째로 달라지는 원소 쌍의 이터레이터를 반환함**equal(first1, last1, first2)**:[first1, last1)과[first2, first2 + (last1 - first1))두 범위가 같은지 비교**adjacent_find(first, last)**:[first, last)인접한 두 원소가 같은 이터레이터를 반환**search(first, last, s_first, s_last)**:[first, last)범위 내에서, 서브시퀀스[s_first, s_last)의 첫 등장을 탐색
Modifying Sequence Operations
- 컨테이너의 원소들을 직접적으로 변경하게 되는 연산들
copy(first, last, result):[first, last)범위의 원소들을result로 시작하는 다른 범위로 복사replace(first, last, old_value, new_value):[first, last)범위에 존재하는 원소들에 대해,old_value를new_value로 바꿈remove(first, last, value):[first, last)범위에서value를 찾아 삭제하고, 뒤 원소들을 앞으로 당김swap_ranges(first1, last1, first2):[first1, last1)범위 내 원소들을first2로 시작하는 다른 범위와 swapreverse(first, last):[first, last)범위의 원소들을 뒤집음
Sorting Operations
- 컨테이너의 원소들을 정렬하는데에 쓰이는 연산들
sort(first, last):[first, last)범위의 원소들을 오름차순으로 정렬stable_sort(first, last):[first, last)범위의 원소들을 오름차순으로 안정정렬(같은 원소에 대해 순서의 무결성 보장)partial_sort(first, middle, last):[first, middle)범위의 원소들을 오름차순 정렬nth_element(first, nth, last):nth원소를 고정한채로,[first, nth), (nth, last)범위를 부분정렬함.
Binary Search Operations
- 정렬된 컨테이너의 원소들을 효율적으로 검색하기 위한 이진 탐색 연산들
lower_bound(first, last, value):[first, last)범위의 원소들을 탐색하여,value보다 크거나 같은 첫번째 원소를 반환함.upper_bound(first, last, value):[first, last)범위의 원소들을 탐색하여,value보다 큰 첫번째 원소를 반환함.equal_range(first, last, value):(lower_bound, upperbound)의std::pair객체를 반환함.binary_search(first, last, value): 범위 내 특정 원소가 존재하는지 판단함.
Set Operations
- 정렬된 컨테이너의 원소들에 대한 집합 연산들
set_union(first1, last1, first2, last2, result): 각 두 범위에 해당하는 집합의 합집합을result에 구축함.set_intersection(first1, last1, first2, last2, result): 각 두 범위에 해당하는 집합의 교집합을result에 구축함.set_difference(first1, last1, first2, last2, result): 각 두 범위에 해당하는 집합의 차집합을result에 구축함.set_symmetric_difference(first1, last1, first2, last2, result): 각 두 범위에 해당하는 집합의 대칭차집합(\( (A-B) + (B - A) = (A \cup B) - (A \cap B) \) )을result에 구축함.
Heap Operations
- 최대 힙을 만들고 조작하기 위한 연산들
make_heap(first, last):[first, last)범위를 힙 구조를 띄도록 재정렬함.push_heap(first, last):[first, last-1)범위로 정의된 힙에 원소를 삽입함.pop_heap(first, last): 힙 컨테이너에서 최댓값(루트노드)을 맨 마지막 자식노드와 교환하고, 루트 노드를 재정렬함. (pop_back()은 사용자가 직접 호출해야함.)sort_heap(first, last):[first, last)범위의 힙 컨테이너를 재정렬함
Min/Max Operations
- 최댓값 최솟값을 찾기 위한 연산들
min(a, b):a와b중 작은 것을 반환함.max(a, b):a와b중 큰 것을 반환함.min_element(first, last):[first, last)범위 중 가장 작은 원소를 반환함.max_element(first, last):[first, last)범위 중 가장 큰 원소를 반환함.
Numeric Operations
- 수학적인 연산들
accumulate(first, last, init):[first, last)범위의 누적합을 계산. (누적합 =init+ 범위 내 모든 원소)inner_product(first1, last1, first2, init):[first, last)범위와first2로 시작하는 범위에 대해 내적을 계산. (내적 =init+ 두 범위에 대한 순차적인 곱의 누적합)partial_sum(first, last, d_first):[first, last)범위에 대한 부분합을 순차적으로 계산하여d_first로 시작하는 범위에 씀. ([0] = [0], [1] = [0:1], [2] = [0:2] … )adjacent_difference(first, last, result):[first, last)범위에서, 인접 원소에 대한 차이를result로 시작하는 범위에 씀. ([0] = [0], [1] = [1] - [0], [2] = [2] - [1] … )
Leave a comment