저번 시간은 map 컨테이너에 대해 알아보았다.
map은 key와 value를 함께 관리할 수 있는 연관 컨테이너였다.
단, key가 중복이 허용되지 않았다.
그럼 key를 중복으로 사용하고 싶다면 어떻게 해야할까?
그 해답인 multimap에 대해 알아보자.
1. multimap이란?
multimap은 map과 매우 유사한 연관 컨테이너이다.
균형 이진트리(중위순회)이며, key와 value의 쌍(pair)인 원소들의 집합으로 이루어져 있다.
multimap의 특징은 map과 달리 key값이 중복이 된다는 것이다.
key를 중복하여 사용하고자 할때 해당 컨테이너를 이용하면 프로그램을 유연하게 구현가능하므로 기억해두자.
map과 같이 원소 삽입시(insert) 자동 정렬되며, default 기준 오름차순정렬이다.
multimap을 사용하기 위해선 <map> 헤더파일을 include 해주어야하며(multimap이 아니다!!),
std::multimap<[key 데이터타입], [value 데이터타입]> [변수이름]; 형식으로 선언해 사용할 수 있다.
(using namespace std;로 std 생략하여 편하게 작성가능)
2. multimap - 생성자
multimap 생성자는 다음과 같이 사용 가능하다. 아래부터 key는 int, value는 char형이라 가정하고 작성하겠다.
- multimap<int, char> mm;
- multimap<int, char, greater<int>> mm;
- key를 내림차순으로 정렬하는 빈 multimap 컨테이너 mm을 생성
- multimap<int, char> mm2(mm);
3. multimap - 멤버 함수 및 접근 방식
다음은 multimap 멤버 함수와 접근 방식이다. (multimap<int, char> m 선언 기준)
- 멤버 함수
- mm.begin();
- mm의 맨 처음 원소를 가리키는 반복자 리턴
- iterator = mm.begin();
- mm.end();
- mm의 마지막 원소를 가리키는 반복자 리턴
- iterator = mm.end();
- mm.clear();
- mm.size(), mm.max_size();
- mm의 원소 갯수를 반환
- mm의 최대 사이즈 반환
- mm.empty();
- mm.count(k);
- mm.insert(p), m.emplace(p);
- mm에 p(pair)라는 객체 추가
- insert 성공시 true 반환, key 이미 존재하여 실패한 경우는 false 반환
- emplace로도 추가 가능
- mm.insert(pair<int, char>(k, v)), m.emplace(pair<int, char>(k, v));
- mm에 k(key), v(value) 값 삽입
- insert 성공시 true 반환, key 이미 존재하여 실패한 경우는 false 반환
- emplace로도 추가 가능
- mm.erase(k);
- mm에서 k(key) 값 해당 요소를 찾아 제거
- mm.erase(start, end), mm.erase(iterator);
- mm에서 start부터 end 범위 원소 모두 제거
- iterator가 가리키는 key 제거
- mm.find(k), mm.find(k)->second;
- mm에서 k(key) 값을 찾아 반복자 형태로 반환
- mm에서 k(key) 값을 찾아 value 출력
- 못찾은경우 반복자 end 리턴
- mm2.swap(mm);
- mm.upper_bound(k1), mm.lower_bound(k2);
- k1(key) 값 해당되는 맨 마지막 원소의 다음을 가리키는 반복자 반환(폐구간 ")"로 사용)
- k2(key) 값 해당하는 맨 첫번째 원소를 가리키는 반복자 반환(개구간 "["로 사용)
- mm.equal_range(k);
- k(key)이란 원소가 시작하는 구간과 끝나는 구간 반복자 pair 객체 반환
- pair의 first는 lower_bound 반환값, second는 upper_bound 반환값
- [ first, second )
- mm.key_comp(), m.value_comp();
- 정렬 기준 조건자 반환(key기준, value 기준 선택)
- 접근 방식
- iterator를 통한 접근
- multimap<int, char>::iterator mmit;
- mmit->first(key), mmit->second(value) 형식으로 접근가능
4. multimap - 연산자
multimap의 연산자이다.
- ==, !=
- == : 두 multimap 컨테이너의 모든 원소가 같으면 참, 아니면 거짓
- != : 두 multimap 컨테이너에서 하나라도 원소가 다르면 참, 아니면 거짓
- <, >, <=, >=
5. multimap 구조 및 실습
위에서 설명한 multimap의 구조는 균형 이진트리로 다음 그림과 같다.
계속해서 말하지만 key의 중복이 허용된다.
multimap 컨테이너를 이용하여 실습을 진행해보았다.
#include <iostream>
#include <map>
using namespace std;
int main(void) {
multimap<int, char> mm;
multimap<int, char>::iterator mmit;
mm.insert(pair<int, char>(1, 'a')); //insert key 1, value 'a'
mm.insert(pair<int, char>(2, 'b')); //insert key 2, value 'b'
mm.insert(pair<int, char>(3, 'c')); //insert key 3, value 'c'
mm.insert(pair<int, char>(4, 'd')); //insert key 4, value 'd'
mm.insert(pair<int, char>(3, 'e')); //insert key 3, value 'e' > Allow!
for (mmit = mm.begin(); mmit != mm.end(); mmit++) {
cout << "key값 : " << mmit->first; //iterator->first는 key
cout << ", value값 : "<< mmit->second << endl; //iterator->second는 value
}
cout << "mm.erase(1) 수행" << endl;
mm.erase(1); //key가 1인값 제거
for (mmit = mm.begin(); mmit != mm.end(); mmit++) {
cout << "key값 : " << mmit->first; //iterator->first는 key
cout << ", value값 : " << mmit->second << endl; //iterator->second는 value
}
cout << "mm.size : " << mm.size() << endl; //크기
cout << "mm.max_size : " << mm.max_size() << endl; //최대 사이즈
cout << "mm.count(3) : " << mm.count(3) << "개" << endl; //key가 3인 원소 갯수
cout << "mm.find(2)->second : " << mm.find(2)->second << endl; //key가 2인 원소 value
cout << "mm.lower_bound(3) : "<< mm.lower_bound(3)->first << ", " << mm.lower_bound(3)->second << endl;
cout << "mm.upper_bound(3) : " << mm.upper_bound(3)->first << ", " << mm.upper_bound(3)->second << endl;
return 0;
}
실행결과는 다음과 같다.
여기까지 multimap과 동시에 stl 파트를 마친다. 다음시간엔 클래스에 대해 알아볼 예정이다.