⊙ 맵
- 맵은 키와 값의 쌍을 관리한다.
- 연관이 있는 두개의 값을 쌍으로 관리 한다는 점에 연관 컨테이너라고 함
- 정렬된 상태로 요소를 저장하므로 빠르게 검색할 수 있다.
- 두 컨터네이너 모두 키를 정렬 및 검색의 기준으로 사용한다.
- 단순 맵은 키의 중복을 허락하지 않음, 한 키에 하나만 저장할 수 있다.
- 멀티맵은 키의 중복을 허용하므로 여러 개의 키를 저장할 수 있다.
- 데이터의 관계를 표현하는데 주로 사용
ㅇ 맵 클래스
- 단순 맵 정의
template<class Key, class T, class BinPred = less<Key>, class A = allocator<T> >
class map { ... }
- 멀티 맵도 이름만 다를 뿐 정의는 같다.
- 데이터에 해당하는 값의 타입을 두 번째 인수로 요구
- 나머지 비교 함수 객체나 할당기는 셋과 동일하며 디폴트가 무난하게 지정되어 있어 생략가능
- 키와 값의 타입은 디폴트가 없으므로 반드시 지정해야 한다.
- 정수, 실수, 문자열 등등이 가능, 사용자 정의도 조건이 맞는다면 사용 가능
- 두 타입이 같이 필요 없이 달라도 상관없다.
ㅇ 생성자
explicit map(const BinPred& comp = BinPred()); /// 디폴트
map(const map& x); /// 복사 생성자
map(InIt first, InIt last, const BinPred& comp = BinPred()); /// 반복자 구간
- 맵의 반복자는 셋과 마찬가지로 양방향 반복자이다.
ㅇ 삽입 삭제
- 맵에 요소를 추가 할 때는 insert 함수를 사용하는데 셋과 원형이 완전히 일치한다.
pair<iterator, bool> insert(const value_type& val); ///ex) m.insert(pari<string, int) ("문자열", 1234);
iterator insert(iterator it, const value_type& val); /// 삽입 위치 제공
void insert((iterator first, iterator last); /// 반복자 구간 제공
- 맵은 insert 함수외에 좀 더 편리한 삽입 방법을 제공하는데 [] 연사자와 대입 연산자도 요소를 사입할 수 있다.
T& operator[](const Key& k); /// ex) m["문자열"] = 1234;
- []연산자는 이미 삽입되어 있는 요소의 값을 수정할 때도 사용
- 맵에 의해 오버로딩되어 잇는 []연산자는 배열의 첨자 연산자인[]와는 의미가 완전히 다르다.
- 배열의 요소를 읽는 []연산자는 피연산자로 정수만 취할수 있지만 맵의 []연산자는 키의 타입으로 지정된 타입을 취하므로 정수가 아닌 문자열이나 실수를 피연산자로 받을 수 있다.
- 단 []연산자는 맵에만 정의되어 있고 멀티맵에는 정의되어 있지 않다.
- 멀티맵에서는 값을 삽입할 때 insert함수만 사용가능, 수정할 때도 검색함수를 사용해야 한다.
- erase 함수 ==> 요소를 삭제, 셋과 완전히 일치
- 반복자가 지정한 요소하나, 반복자 구간의 모든 요소, 특정한 키를 자기는 요소를 삭제가능
- 맵의 경우 키를 가진 요소가 여러개 발견되면 전부 삭제
1 iterator erase( iterator it);
2 iterator erase( iterator first, iterator last );
3 size_type erase(const Key& key);
4
5 #include <iostream>
6 #include <string>
7 #include <map>
8 using namespace std;
9
10 void main()
11 {
12 map<string,int> m;
13 m.insert(pair<string,int>(string("서울"),1000));
14 m.insert(pair<string,int>("부산",500));
15 m["대전"]=400;
16 m["대구"]=300;
17 m["광주"]=200;
18 m["인천"]=100;
19 m["독도"]=1;
20
21 m.erase(m.begin());
22 m.erase("인천");
23
24 map<string,int>::iterator it;
25 for (it=m.begin();it!=m.end();it++) {
26 cout << it->first << ":" << it->second << "만명" << endl;
27 }
28 }
ㅇ 검색
- 맵을 검색할 때는 find멤버 함수를 사용, 상수버전과 비상수번저이 중복 정의 되어 있음
iteratir find(const Key &val);
const_iterator find( const Key& val) const;
- 인수로 검색하고자 하는 키를 전달, 정렬되어 있는 상태를 활용하여 빠른 속도로 키값을 가진 요소를 찾아 그 반복자를 리턴한다.
1 #include <iostream>
2 #include <string>
3 #include <map>
4 #include <algorithm>
5
6 using namespace std;
7
8 void main()
9 {
10 map<string,int> m;
11 m["서울"]=1000;m["부산"]=500;m["대전"]=400;m["대구"]=300;
12 m["광주"]=200;m["인천"]=100;m["독도"]=1;
13
14 map<string,int>::iterator it;
15 it=m.find("부산");
16 if (it == m.end()) {
17 cout << "맵에없는도시입니다." << endl;
18 } else {
19 cout << it->first << "의인구는" << it->second << "만명이다." << endl;
20 }
21 }
- 맵의 find 멤버 함수는 있으면 어디쯤 있다. 없으면 없다는 확정적인 결과를 리턴하는 데 비해 멀티 맵의 find는 여러 개의 요소 중 어떤 것을 검색할지 알 수 없다.
키에 해당하는 요소가 여러 개 있을 수 있는데 그 중의 하나를 검색할 뿐이다.
- 여러 개의 키 중 처음이나 마지막 일치하는 요소가 여러 개 있을 수 있는데 그 중의 하나를 검색할 뿐이다. 여러 개의 키 중 처음이나 마지막 일치하는 요소를 찾고 싶다면
lower_bound, upper_bound 멤버 함수를 사용해야 한다. 이런 특성은 셋, 멀티 셋과 같다.
- 맵을 검색할 때 전역 find 알고리즘은 사용할 수 없다. 위 예제의 검색 코드를 다음과 수정한후 컴파일 하면 컴파일 되지 않는다.
it = find(m.begin(), m.end(), "부산");
it = find( m.begin(), me.end(), pair<string, int>("부산",500);
- cout << "부산의 인구는 " << m["부산"] << "만 명이다." << endl;
컴파일도 잘 되고 결과도 제대로 나온다. 그러나 이 코드는 정확한 검색 코드가 아닐 뿐더러 아주 위험한데 다음과 같이 수정해 보자.
cout << "춘천의 인구는 " << m["춘천"] << "만 명이다." << endl
[] 연산자의 정의에 의해서 m["춘천"] 연산식은 맵에 춘천이 있는지 보고 없으면 일단 춘천을 먼저 삽입하나. 이때 키만 삽입할 수는 없으므로 값 타입의
디폴트 생성자로 값까지 만들어서 넣게 되는데 m의 값 타입은 정수이므로 int()의 결과인 0이 값으로 대입될 것이다. 그리고 값에 대한 레퍼런스가 리턴되는데 이 값이
그대로 출력되므로 춘천에 아무도 안산다는 거짓말을 하게 된다.
평가만 해도 삽입이 되어 버려 다소 비상식적인데 이는 []연산자가 검색용으로 오버로딩되어 있지 않고 편리한 삽입을 위해 오버로딩되어 있기 때문이다.
이 연산자로 검색도 할 수 있다면 좋겠으나 한연산자로 두 가지 일을 할 수는 없으니 STL 설계자는 삽입을 하는 것으로 선택을 한 것이다. 따라서 이 연산자의 특성을
잘 이해하고 사용하는 수밖에 없다.
ㅇ 수정
- [] 연산자는 키가 없으면 삽입하지만 이미 존재할 경우는 해당 요소의 값에 대한 래퍼런스를 리턴 ==> 수정하는 용도로 사용
m["부산"] = 600;
- 만약 부산이 없다면 부산을 새로 만들고 600을 대입할 것이다.
it = m.find("부산");
it->second = 600;
※ 어떤 방법을 쓰더라도 키는 변경할 수 없다.
- 맵을 수정하는 코드는 컴파일 에러로 처리된다.
it->first = "평양";
- 맵의 요소 타입이 pair(Key, T)가 아니라 pair(const Key, T)로 되어 있어 키믐 무조건 수정 불가능하다.
- 키는 오로지 정렬 기준으로만 사용되므로 일단 삽입되면 절대로 수정할 수 없다.
- 셋은 이런 안전자이치가 없다 왜냐면 키 자체가 값이라 객체의 다른 멤버를 수정하는 것을 허락해야 하기 때문이다.
- 만약 맵의 키를 꼭 수정하고 싶다면 삭제했다가 다시 삽입하는 수밖에 없다.
ps : 출처 및 자세한 내용은 www.WinAPI.co.kr 참고
'[ C/ C++ 프로그래밍 ] > [ STL ]' 카테고리의 다른 글
[ 혼연 정리 ] 연관 컨테이너 - 8 [ 컨테이너 어댑터 ] (0) | 2010.06.24 |
---|---|
[ 혼연 정리 ] 연관 컨테이너 - 7 [ 맵 ] (0) | 2010.06.24 |
[ 혼연 정리 ] 연관 컨테이너 - 2 [ 셋 ] (0) | 2010.06.24 |
[ 혼연 정리 ] 연관 컨테이너 - 1 [ 셋 ] (3) | 2010.06.24 |
[ 혼연 정리 ] 시퀀스 컨테이너 - 9 [ 리스트 ] (0) | 2010.06.24 |