2. 지금 PT는 뇌를 자극하는 C++ STL을 기반으로 작성되었
으며 그 외에 기타등등 구글신님과 개인적인 취향에 따라 만
들었습니다.
따라서 개인적인 의견이 들어가 있을 수 있음을 알려드립니다.
STL은 저만 모른다고 생각하기 때문에 일부러 고른 주제에요.
혼자 하다보면 막 혼자 이상하게 이해하더라구요...
틀린 내용이 있을수도..
도망가세요 얼른!!
3. 또 만들다 보니 생각보다 매우 지쳐서 내용이 많지 않아요.
빨리 하고 밥먹으러가요...
그리고 내용이 매우 재미가 없네요 ...
짤방도 없어요...
떨려요 집에 가고싶어요...
도망가세요 얼른!!
5. Standard Template Library 의 약자
프로그램에 필요한 자료구조와 알고리즘을 템플릿으로 제공하는 라이브러리
사전적 의미 : 형판, 본보기 , 틀!!
C++적 의미 : 함수나 클래스코드를 찍어
내듯이 생산할 수 있도록 일반화 시키
는 도구
http://blog.naver.com/madplay/220187782482
Template(템플릿)
7. • 함수 템플릿
1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<typename T>
void Print(T a, T b)
{
cout << a << ", " << b << endl;
}
int main()
{
Print(10, 20);
Print(20.5, 10.5);
Print("Hello", "World");
return 0;
}
매개변수에 따라 함수를 만들어야
했던 이전 방식과 달리 한번에 여러
매개변수를 전달 받을 수 있다는 장
점이 있다.
8. 템플릿을 사용하지 않았다면 오버로딩을 통해서 일일히 작성해야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void Print(int a, int b)
{
cout << a << ", " << b << endl;
}
void Print(double a, double b)
{
cout << a << ", " << b << endl;
}
void Print(string a, string b)
{
cout << a << ", " << b << endl;
}
9. • 클래스 템플릿
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template<class T = int>
class Array
{
T *buf;
int size;
int capasity;
};
int main()
{
Array<int> intarr;
Array<> intarr2;
Array<double> doublearr;
Array<string> stringarr;
return 0;
}
클래스 템플릿은 명시적으로 템플릿 타입
을 선언해주어야 하고, 미리 기본으로 처리
할 타입을 선언할 수 있다. 또 미리 선언했
기 때문에 타입을 쓰지 않을 수 있지만 미리
선언하지 않은 경우에는 반드시 타입을 적
어주어야만 한다.
10. Standard Template Library 의 약자
• Container(컨테이너)
• Iterator(반복자)
• Algorithm(알고리즘)
• Function Object(함수 객체)
• Adaptor(어댑터)
• Allocator(할당기)
로 구성되어 있으며,
Container(컨테이너) Iterator(반복자) Algorithm(알고리즘)
이렇게 세개로 나누는 경우도 있다.
11. Container(컨테이너)는 같은 타입을 저장, 관리 목적으로 만들어진 클래스이다.
또 컨테이너는 크게 2가지로 나눌 수 있고 총 7가지의 컨테이너를 제공한다.
• Starndard Sequence Container(표준 시퀀스 컨테이너)
로 구성되어 있으며,
: 삽입되는 순서에 따라 순서대로 저장한다.
• Vector
• Deque
• List
• Standard Associative Container(표준 연관 컨테이너)
: 삽입 순서에 상관 없이 정렬방법에 따라서 저장한다.
• Set
• Multiset
• Map
• Multimap
String컨테이너 같은 경우는 시퀀스 컨테이너의 일종이지만
표준 컨테이너의 요구사항을 충족시키지 않기 때문에 제외하였다.
Effective C++의 저자 같은 경우에는 표준 시퀀스 컨테이너에 포함시키긴 한답니다.
12. 컨테이너를 다른 방법으로 나누자면
로 나눌 수 있다.
• Array-based Container(배열 기반 컨테이너)
: 데이터 여러 개가 하나의 메모리 단위에 저장한다.
• Vector
• Deque
• Node-based Container(노드 기반 컨테이너)
: 데이터 하나를 하나의 메모리 단위에 저장한다.
• List
• Set
• Multiset
• Map
• Multimap
15. • Vector(벡터)
: 대표적인 시퀀스 컨테이너
#include <vector>
vector<int> v;
배열과 비슷하고 동적으로 할당해 사용할 수 있습니다.
1. 추가
v.push_back(n); //n을 벡터의 맨 뒤에 추가
v.insert(I, x); //원소 i의 위치에 x를 추가
2. 크기 확인
v.size(); //벡터의 원소 개수를 반환, 반환 타입은 unsigned int
vector<int>::size_type n = v.size(); // n에 벡터의 크기를 저장
3. 메모리 공간 예약
v.reserve(n); //벡터의 크기(capacity)를 n으로 설정함.
4. 메모리 공간 할당
v.resize(n); //벡터의 크기(size)를 n으로 설정함.
5. 벡터 비우기
v.clear(); //벡터의 요소 모두 삭제
6. 벡터가 비었는지 확인
v.empty(); //벡터가 비어있으면 True, 아니면 false
16. 1
2
3
4
5
6
7
8
9
10
11
int main()
{
std::vector<int> v;
v.reserve(200);
for (int i = 0; i < 100; i++)
v.push_back(i);
return 0;
}
• Vector(벡터)
Reserve와 Resize의 차이
1
2
3
4
5
6
7
8
9
10
11
int main()
{
std::vector<int> v;
v.resize(200);
for (int i = 0; i < 100; i++)
v.push_back(i);
return 0;
}
17. • Vector(벡터)
: 대표적인 시퀀스 컨테이너
#include <vector>
vector<int> v;
배열과 비슷하고 동적으로 할당해 사용할 수 있습니다.
7. 벡터 메모리 해제
vector<int>().swap(v); //clear는 내용만 비울뿐 메모리 해제를 하지 않습니다
8. 벡터끼리 값 바꾸기
v1.swap(v2); //같은 인덱스끼리 값을 바꿈
9. 특정 인덱스로 접근하기
v.front(); //첫번째 원소로 접근
v.back(); //마지막 원소로 접근
v[i]; //i번째 원소로 접근
v.at(i); //i번째 원소로 접근
v.rbegin(); //마지막 원소로 접근 (reverse begin)
v.rend(); //첫번째 원소로 접근 (reverse end)
18. • Vector(벡터)
: 대표적인 시퀀스 컨테이너
#include <vector>
vector<int> v;
배열과 비슷하고 동적으로 할당해 사용할 수 있습니다.
10.특정 원소값 할당하기
v.assign(n, x); //n개의 원소에 x값을 할당
//미리 입력받은 데이터는 버리고
//assign함수로 요구받은 만큼 데이터를 덮어
쓴다.
11.특정 위치에 원소값 넣기
v.insert(i, x); //i번째의 위치에 x값을 추가
v.insert(i, n, x); //i번째의 위치에 x값을 n개만큼 추가
12.특정 위치의 원소값 삭제
v.erase(i); //i번째의 위치의 원소를 삭제
v.erase(i, i+2); //i번째부터 i+2번째까지의 원소를 삭제
19. • Vector(벡터)
v.at(i)와 v[i]의 차이
: v.at(i)는 배열의 크기를 검사해 범위에 벗어나면 out_of_range 예외를 발생시키
고,
v[i]는 배열의 크기를 검사하지 않기때문에 메모리 접근 오류를 발생 시킬 수 있
습니다.
Assign을 사용하면 기존에 있던 배열을 모두 덮어씁니다. Capacity는 유지하고
size만 변경됩니다.
for(vector<int>::size_type i = 0; i< v.size; i++) v[i];
↔ for(vector<int>::iterator iter = v.begin(); iter != v.end(); iter++) *iter;
20. Vector(벡터) 특징
강점
개별 원소들을 index로 접근이 가능하다
원소를 컨테이너의 끝에 삽입/제거 하는 것이 빠르다
어떠한 순서로도 원소들을 순회할 수 있다. 즉, Random access iterating이 가능함.
일반적으로 vector는 다른 두 개의 시퀀스 컨테이너인 deque, list에 비해 개별 원
소에 대한 접근 속도와 컨테이너의 끝에서 삽입/제거하는 속도가 가장 빠르다.
약점
컨테이너의 끝 위치가 아닌 곳에서 삽입/제거 수행시 그 성능은 deque/list에 비
해 현저히 떨어진다.
주의
동적으로 컨테이너의 크기가 확장/축소되는 것이 편하기는 하나, 확장시의
reallocation은 비용이 꽤 크다.
capacity를 확장 시켜줄 수 있는 적절한 크기의 reserve로 인한 메모리 확보가 중
요.
21. • Deque
: 시퀀스 컨테이너의 한 종류
벡터의 단점을 보완함
#include <deque>
deque<int> dq;
1. 추가
dq.push_back(n); //n을 데큐의 맨 뒤에 추가
dq.push_front(n); //n을 데큐의 맨 앞에 추가
dq.insert(I, x); //원소 i의 위치에 x를 추가
2. 크기 확인
dq.size(); //데큐의 원소 개수를 반환, 반환 타입은 unsigned int
deque<int>::size_type n = dq.size(); // n에 데큐의 크기를 저장
3. 메모리 공간 예약
dq.reserve(n); //데큐의 크기(capacity)를 n으로 설정함.
4. 메모리 공간 할당
dq.resize(n); //데큐의 크기(size)를 n으로 설정함.
5. 데큐 비우기
dq.clear(); //데큐의 요소 모두 삭제
22. • Deque
: 시퀀스 컨테이너의 한 종류
벡터의 단점을 보완함
#include <deque>
deque<int> dq;
6. 데큐가 비었는지 확인
dq.empty(); //데큐가 비어있으면 True, 아니면 false
7. 데큐 메모리 해제
deque<int>().swap(v); //clear는 내용만 비울뿐 메모리 해제를 하지 않는다
8. 데큐끼리 값 바꾸기
dq1.swap(dq2); //같은 인덱스끼리 값을 바꿈
9. 특정 인덱스로 접근하기
dq.front(); //첫번째 원소로 접근
dq.back(); //마지막 원소로 접근
dq[i]; //i번째 원소로 접근
dq.at(i); //i번째 원소로 접근
dq.rbegin(); //마지막 원소로 접근 (reverse begin)
dq.rend(); //첫번째 원소로 접근 (reverse end)
23. Deque(데큐) 특징
강점
개별 원소들을 index로 접근이 가능하다.
원소를 컨테이너의 끝 뿐 아니라, 앞에서도 삽입/제거 하는 것이 빠르다.
어떠한 순서로도 원소들을 순회할 수 있다.
약점
컨테이너의 끝이나 시작 위치가 아닌 곳에서 삽입/제거 수행시 그 성능은 벡터
에 비해 떨어진다.
주의
동적으로 컨테이너의 크기가 확장/축소되는 것이 편하기는 하나, 확장시의
reallocation은 비용이 크다.
capacity를 확장 시켜줄 수 있는 적절한 크기의 reserve로 인한 메모리 확보가
중요.
24. Deque와 Vector의 다른점
메모리 부족시의 벡터
1 2 3 4
메모리 부족시의 데큐
1 2 3 4
전체크기 재할당 후 데이터 복사
1 2 3 4
부분크기 재할당만 진행
1 2 3 4
일정크기로 나눈 메모리를 2칸이라고 가정
Vector는 capacity 부족으로 재할당을 받으면 지금의 크기보다 더 큰 메모리를 가
진 벡터를 할당받아서 복사한 뒤 사용을 해 속도가 떨어지는 측면이 있었는데,
Deque는 capacity 부족으로 재할당을 받으면 일정 크기로 나눈 메모리의 크기만
큼만 재할당 받아 이전 메모리를 삭제하거나 복사하는 등의 연산을 하지 않는다.
25. Deque와 Vector의 다른점
처음과 끝의 삽입, 삭제시 벡터보다 속도가 빠르다.
중간 삽입, 삭제의 경우 인덱스의 앞의 원소갯수가 뒤의 원소갯수보다 작으면
앞쪽에 메모리를 할당하여 앞쪽으로 밀어내며 삽입, 삭제하고, 뒤의 원소갯수
가 앞의 원소갯수보다 작으면 뒤쪽에 메모리를 할당하여 뒤쪽으로 밀어내며
삽입, 삭제 한다.
강점
저장 원소가 많고 메모리 할당량이 큰 경우 vector에 비해 확장 비용이 절감된
다.
약점
컨테이너 처음부터 끝까지 연속 메모리 공간이 아니므로, vector에서 가능했던
원소들간 포인터 연산이 불가능하다.
26. • List(리스트)
: 시퀀스 컨테이너이면서 노드 기반 컨테이너
노드 단위로 저장되며 이중연결리스트로 구현됨
#include <list>
list<int> lt;
1. 추가
lt.push_back(n); //n을 리스트의 맨 뒤에 추가
lt.push_front(n); //n을 리스트의 맨 앞에 추가
lt.insert(I, x); //원소 i의 위치에 x를 추가
2. 요소 개수 확인
lt.size(); //리스트의 원소 개수를 반환, 반환 타입은 unsigned int
list<int>::size_type n = lt.size(); // n에 요소 개수를 저장
3. 리스트 비우기
lt.clear(); //리스트의 요소 모두 삭제
4. 리스트가 비었는지 확인
lt.empty(); //리스트가 비어있으면 True, 아니면 false
27. • List(리스트)
: 시퀀스 컨테이너이면서 노드 기반 컨테이너
노드 단위로 저장되며 이중연결리스트로 구현됨
#include <list>
list<int> lt;
5. 리스트 메모리 해제
list<int>().swap(v); //clear는 내용만 비울뿐 메모리 해제를 하지 않는다
6. 리스트끼리 값 바꾸기
lt1.swap(lt2); //같은 인덱스끼리 값을 바꿈
7. 특정 인덱스로 접근하기
lt.front(); //첫번째 원소로 접근
lt.back(); //마지막 원소로 접근
lt.rbegin(); //마지막 원소로 접근 (reverse begin)
lt.rend(); //첫번째 원소로 접근 (reverse end)
8. 조건이 참인 원소 제거
lt.remove_if(조건) //조건이 참인 모든 원소 제거
9. 삭제
lt.remove(n) //원소가 n인 원소 삭제
28. • List(리스트)
: 조건 원소 삭제 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool Predicate(int n)
{
return 10 <= n && n <= 30;
}
int main()
{
lt.push_back(10);
lt.push_back(40);
lt.push_back(10);
lt.remove_if(Predicate);
return 0;
}
특이하게 함수 이름을 매개변수로 넘겨줌
29. • List(리스트)
: 시퀀스 컨테이너이면서 노드 기반 컨테이너
노드 단위로 저장되며 이중연결리스트로 구현됨
#include <list>
list<int> lt;
10.배열 이어붙이기
lt1.splice(i, lt2); //이어 붙이고 나면 lt2에는 아무런 요소도 남지 않는다.
lt1.merge(lt2); //같은방법으로 정렬된 배열을 이어붙이기
붙이면 정렬이 된 결과를 얻을 수 있다
11.배열 뒤집기
lt.reverse();
12.인접한 중복원소 지우기
lt.unique(); //매개변수로 조건을 주면 조건이 참일경우 삭제
13.배열 정렬하기
lt.sort(); //오름차순으로 정렬 default
lt.sort(grater<int>()); //내림차순으로 정렬
30. List(리스트)의 특징
강점
컨테이너의 어느 위치에서도 삽입/제거가 빠르다.
원소들의 컨테이너 내 순서 이동이 빠르다.
vector와 deque와 다르게 list의 가장 큰 강점은 컨테이너 내 어느 위치에서도
원소의 삽입/제거가 빠르다는 것이다.
약점
원소의 index로 직접 접근이 불가능하다.
: 특정 원소에 접근하려면 처음이나 끝에서부터 선형 탐색을 하여야만 한다.
컨테이너 내 원소 순회는 forward / reverse 순회만 가능하며, 느리다.
원소들간 상호 연결 정보를 위해 추가적인 메모리가 사용된다.
31. • Set(셋)
: 연관컨테이너 중 단순한 컨테이너
key(키)라고 불리는 원소의 집합
#include <set>
set<int> s;
1. 추가
s.insert(n); //n을 배열에 추가, 중복값이면 추가 안됨
2. 추가 성공여부 확인
pair<set<int>::iterator, bool> pr = s.insert(n);
//성공시 true, 실패시 false
3. 내림차순 정렬
set<int, grater<int>> s; //set의 default 정렬은 오름차순
4. 특정 원소 개수 세기
s.count(n) //배열에 n이 몇 개 있는지 확인
5. 특정 원소 찾기
s.find(n) //배열에 n이 있는지 확인
//있으면 위치 반환
32. Set(셋)의 특징
강점
원소 검색 속도가 빠르다.
원소 삽입과 동시에 자동 정렬 된다.
여러 찾기 관련 함수를 제공한다.
중복된 원소는 삽입되지 않는다.
약점
원소의 index로 직접 접근이 불가능하다.
Front와 back등 컨테이너의 앞 뒤에 추가 제거 하는 함수를 제공하지 않는다.
33. • multiset(멀티셋)
: 연관컨테이너 중 단순한 컨테이너
key(키)라고 불리는 원소의 집합
#include <set>
multiset<int> ms;
1. 추가
ms.insert(n); //n을 배열에 추가, 반환값은 반복자
2. 내림차순 정렬
multiset<int, grater<int>> ms; //default 정렬은 오름차순
3. 특정 원소 개수 세기
ms.count(n) //배열에 n이 몇 개 있는지 확인
4. 특정 원소 찾기
ms.find(n) //배열에 n이 있는지 확인
//있으면 위치 반환
34. multiset(멀티셋)의 특징
중복된 원소를 입력받지만 오름차순으로 정렬됨.
강점
원소 검색 속도가 빠르다.
원소 삽입과 동시에 자동 정렬 된다.
여러 찾기 관련 함수를 제공한다.
약점
원소의 index로 직접 접근이 불가능하다.
Set과의 차이는 단순 중복된 원소를 받을 수 있는지 없는지의 여부다.
35. • map(맵)
: 가장 빈번하게 쓰이는 연관 컨테이너
key와 value를 쌍으로 저장하는 컨테이너
#include <map>
map<int, map> m;
1. 추가
m.insert(pair<int, int>(k, v)); //key가 k이고 value가 v
m[k] = v; //없는 key라면 추가, 있으면 값을
바꿈
2. 출력방법
map<int,int>::iterator iter;
iter->first; //key값
iter->second; //value값
m[k]; //value값 출력할때 사용
3. 추가 성공 여부 확인
Pair<map<int, int>::iterator, bool> pr;
pr->first; //추가한 원소의 위치
pr->second; //원소의 성공 여부 성공하면 true
36. • map(맵)
: 가장 빈번하게 쓰이는 연관 컨테이너
key와 value를 쌍으로 저장하는 컨테이너
#include <map>
map<int, map> m;
4. 정렬하기
map<int, int, grater<int>> m; //내림차순
map<int, int, less<int>> m; //오름차순 default
5. Key값으로 value찾기
iter = m.find(k); //key값으로 요소의 위치를 리턴
iter->first; //key값
iter->second; //value값
37. map(맵)의 특징
강점
원소 검색 속도가 빠르다.
원소 삽입과 동시에 자동 정렬 된다.
여러 찾기 관련 함수를 제공한다.
중복된 원소는 삽입되지 않는다.
약점
Front와 back등 컨테이너의 앞 뒤에 추가 제거 하는 함수를 제공하지 않는다.
Set과의 차이는 map은 항상 key와 value가 한 쌍으로 움직인다는 점이다.
38. • multimap(멀티맵)
: 가장 빈번하게 쓰이는 연관 컨테이너
key와 value를 쌍으로 저장하는 컨테이너
#include <map>
multimap<int, map> mm;
1. 추가
mm.insert(pair<int, int>(k, v)); //key가 k이고 value가 v
2. 출력방법
map<int,int>::iterator iter;
iter->first; //key값
iter->second; //value값
3. 중복 key 검색방법
1
2
3
4
5
6
7
8
int main()
{
pair<multimap<int, int>::iterator,
multimap<int, int>::iterator> iter_pair;
iter_pair = mm.equal_range(3);
return 0;
}
//Key값 3을 갖고 있는 모든 범위
39. • multimap(맵)
: key와 value를 쌍으로 저장하는 컨테이너
3. 중복 key 검색방법
1
2
3
4
5
6
7
8
9
10
11
12
int main()
{
multimap<int, int> mm;
multimap<int, int>::iterator iter;
multimap<int, int>::iterator lower_iter;
multimap<int, int>::iterator upper_iter;
lower_iter = mm.lower_bound(3);
upper_iter = mm.upper_bound(3);
return 0;
}
//Key값 3을 갖고 있는 시작 반복
자//Key값 3을 갖고 있는 끝 반복자
40. multimap(멀티맵)의 특징
중복key를 허용한다. 같은 key를 가지고 있다면 입력 순서대로 자동 정렬된다.
강점
원소 검색 속도가 빠르다.
원소 삽입과 동시에 자동 정렬 된다.
여러 찾기 관련 함수를 제공한다.
약점
Front와 back등 컨테이너의 앞 뒤에 추가 제거 하는 함수를 제공하지 않는다.
Set과의 차이는 map은 항상 key와 value가 한 쌍으로 움직인다는 점이다.
Map과의 차이는 단순 중복key를 허용하는지의 여부다.
41. Iterator(반복자)
• Iterator
: 포인터를 추상화 한 클래스 객체,
포인터가 하지 못하는 더 많은 동작을 수행할 수 있다.
• iterator의 종류
• Input iterator(입력 반복자) : 전방향 읽기
• Output iterator(출력 반복자) : 전방향 쓰기
• Forward iterator(순방향 반복자) : 전방향 읽기, 쓰기
• Bidirectional iterator(양방향 반복자) : 양방향 읽기, 쓰기
• List
• Set
• Multiset
• Map
• Multimap
• Random access iterator(임의 접근 반복자) : 랜덤 읽기, 쓰기
• Vector
• deque
42. Iterator(반복자)
• (Container C)::iterator, C::const_iterator
C::iterator
: 반복자가 가르키는 원소 읽기 쓰기 가능
C::const_iterator
: 반복자가 가르키는 원소 읽기 가능
• (Container C)::reverse_iterator, C::const_reverse_iterator
C::reverse_iterator
: 반복자가 가르키는 원소 거꾸로 읽기 쓰기 가능
C::const_reverse_iterator
: 반복자가 가르키는 원소 거꾸로 읽기 가능