[STL] map 컨테이너



map 컨테이너는 연관 컨테이너 중 자주 사용하는 컨테이너로 원소를 key와 value의 쌍으로 저장한다. set과 다른점이 바로 이것이다. set은 원소로 key 하나만을 정장하지만, map은 원소로 key와 value의 쌍(pair 객테)를 저장한다. 그리고 map은 set처럼 중복 key를 허용하지 않는다. 중복 key를 허용하려면 multimap을 사용해야 한다. 그리고 map의 중요 특징은 연관 컨테이너이며, 노드 기반 컨테이너인데 []연사자를 사용하여 원하는 key에 해당하는 원소의 value에 쉽게 접근이 가능하다. map의 기본 구조를 봐보자.

image

map에서 key값은 유일해야하며 set과 동일하게 원소를 삽입하는 건 insert()를 통해서 가능하다. 그리고 map의 원소는 pair객체로 저장되며, pair.first에는 key값이 그리고 pair.second에는 value값이 들어 있다. 원소를 저장하는 insert()는 pair객체를 인자로 받아서 map에 저장한다. 예시코드를 보자.

#include <iostream>
#include <map>
using namespace std;

void main() {
	//key값이 int형,value값도 int형
	//기본 정렬 기준 less (key값들을 오름차순으로 정렬)
	map<int, int> m;

	m.insert(pair<int, int>(5, 100)); //임시 pair객체 생성 후 저장
	m.insert(pair<int, int>(3, 100));
	m.insert(pair<int, int>(8, 30));
	m.insert(pair<int, int>(4, 40));
	m.insert(pair<int, int>(1, 70));
	m.insert(pair<int, int>(7, 100));

	pair<int, int> pr(9, 50);
	m.insert(pr); //pr객체 생성 후 저장

	map<int, int>::iterator iter;
	for (iter = m.begin(); iter != m.end(); iter++) {
		cout << "(" << (*iter).first << ", " << (*iter).second << ")" << " ";
	}
	cout << endl;

	//반복자는 ->연사자가 오버로딩 되어있기 때문에
	//포인터처럼 멤버를 ->연산자롤 접근할 수 있다.
	for (iter = m.begin(); iter != m.end(); iter++) {
		cout << "(" <<iter->first << ", " << iter->second << ")" << " ";
	}
}

실행 결과

image-20220316101946044

우선 확인 가능한게 기본 정렬 조건인 less로 인해 key값들이 오름차순으로 정렬되어 있는게 보이고, map에 insert()할 때 pair객체를 넘겨줘야하며, pair객체의 first에는 key값이, second에는 value가 들어있는게 확인 된다. 그리고 반복자는 ->연산자가 오버로딩 되어 있기 때문에 ->연산자로 멤버에 접근 할 수 있다.

그리고 map은 set처럼 중복 key를 허용하지 않기 때문에 insert()의 반환값은 저장한 원소를 가리키는 반복자와 성공여부를 pair객체로 반환한다. 예시를 봐보자.

#include <iostream>
#include <map>
using namespace std;

void main() {
	//key값이 int형,value값도 int형
	//기본 정렬 기준 less (key값들을 오름차순으로 정렬)
	map<int, int> m;

	//insert()의 반환값인 pair값을 저장할 pair 객체
	pair<map<int, int>::iterator, bool> pr;

	m.insert(pair<int, int>(5, 100)); //임시 pair객체 생성 후 저장
	m.insert(pair<int, int>(3, 100));
	m.insert(pair<int, int>(8, 30));
	m.insert(pair<int, int>(4, 40));
	m.insert(pair<int, int>(1, 70));
	m.insert(pair<int, int>(7, 100));

	pr = m.insert(pair<int, int>(9, 50));
	//pr.first는 삽입된 원소의 위치를 카리키는 반복자
	//pr.second는 원소 삽입 성공 여부
	if (pr.second == true) {
		cout << "key: " << pr.first->first << ", value: " << pr.first->second << "저장 완료" << endl;
	}
	else {
		cout << "key 9가 이미 m에 있습니다.";
	}

	pr = m.insert(pair<int, int>(9, 50));
	if (pr.second == true) {
		cout << "key: " << pr.first->first << ", value: " << pr.first->second << " 저장 완료" << endl;
	}
	else {
		cout << "key 9가 이미 m에 있습니다.";
	}
}

실행 결과

image

여기서 가장 중요한 점은 pair객체의 first에는 삽입 된 원소의 위치를 가리키는 반복자가 들어있고, second에는 삽입 성공 여부가 들어있다는 것이다. 위의 코드의 pair객체 pr을 그림으로 나타내보겠다.

image

그리고 map의 가장 중요한 특성 []연산자가 사용된다는 것이다. []연사자를 통해서 key,value를 추가하고 수정할 수 있다.즉, 이미 컨테이너안에 key에 해당하는 원소가 없다면 추가하고, 이미 있다면 key에 해당하는 value를 수정한다. 예시를 보자.

#include <iostream>
#include <map>
using namespace std;

void main() {
	//key값이 int형,value값도 int형
	//기본 정렬 기준 less (key값들을 오름차순으로 정렬)
	map<int, int> m;

	m[5] = 100; //key: 5, value: 100을 m에 삽입한다.
	m[3] = 100;
	m[8] = 30;
	m[4] = 40;
	m[1] = 70;
	m[7] = 100;
	m[9] = 50;

	map<int, int>::iterator iter;
	for (iter = m.begin(); iter != m.end(); iter++) {
		cout << "(" << iter->first << ", " << iter->second << ")" << " ";
	}
	cout << endl;

	m[5] = 200; //key: 5의 value를 200으로 갱신한다.

	for (iter = m.begin(); iter != m.end(); iter++) {
		cout << "(" << iter->first << ", " << iter->second << ")" << " ";
	}
}

실행 결과

image

제대로 key와 value가 저장된걸 확인할 수 있고,key 5에 해당하는 value가 수정된걸 확인 가능하다.

map의 기본 정렬 조건은 less이다, 이걸 greater로 바꾸려면 템플릿 형식의 세번째 인자를 이용한다. 예시를 보자.

#include <iostream>
#include <map>
#include<string>
using namespace std;

void main() {
	//greater 정렬 기준의 key:int형, value:string형으로 된 map 컨테이너 생성
	map<int, string, greater<>> m;
	m[5] = "five"; //원소 추가
	m[3] = "three";
	m[8] = "eihgt";
	m[4] = "four";
	m[1] = "one";
	m[7] = "seven";
	m[9] = "nine";

	map<int, string>::iterator iter;
	for (iter = m.begin(); iter != m.end(); iter++) {
		cout << "(" << iter->first << ", " << iter->second << ")" << " ";
	}
	cout << endl;

	cout << m[9] << " ";//key에 맵핑된 value값 출력
	cout << m[8] << " ";
	cout << m[7] << " ";
	cout << m[5] << " ";
	cout << m[4] << " ";
	cout << m[3] << " ";
	cout << m[1] << " ";
	cout << endl;
}

실행 결과

image

딱히 어려운 내용은 없다.

map에서의 찾기 관련 함수(find(), lower_bound(), upper_bound(), equal_range())

#include <iostream>
#include <map>
#include<string>
using namespace std;

void main() {
	map<int, int> m;
	m[5] = 100; //원소 추가
	m[3] = 100;
	m[8] = 30;
	m[4] = 40;
	m[1] = 70;
	m[7] = 100;
	m[9] = 50;

	map<int, int>::iterator iter;
	for (iter = m.begin(); iter != m.end(); iter++) {
		cout << "(" << iter->first << ", " << iter->second << ")" << " ";
	}
	cout << endl;

	iter = m.find(5); //인자로 넘긴 값에 해당하는 key가 m에 있으면 해당 원소를 가리키는 반복자 반환 없으면 end()반환
	if (iter != m.end())
		cout << "key: 5에 매핑된 value: " << iter->second << endl;

	map<int, int>::iterator lower_iter;
	map<int, int>::iterator upper_iter;

	lower_iter = m.lower_bound(5);//5에 해당하는 key값을 가진 원소의 시작 반복자 반환
	upper_iter = m.upper_bound(5);//5에 해당하는 key값을 가진 원소의 끝 반복자 반환
	cout << "구간 [lower_iter,upper_iter)의 순차열 : ";
	for (iter = lower_iter; iter != upper_iter; iter++) {
		cout << "(" << iter->first << ", " << iter->second << ")" << " ";
	}
	cout << endl;

	//반복자쌍을 가지는 pr객체
	pair< map<int, int>::iterator, map<int, int>::iterator> iter_pair;
	iter_pair = m.equal_range(5); //5에 해당하는 lower_bound(),upper_bound()반환

	cout << "구간 [iter_pair.first,iter_pair.second)의 순차열 :";
	for (iter = iter_pair.first; iter != iter_pair.second; iter++) {
		cout << "(" << iter->first << ", " << iter->second << ")" << " ";
	}
}

실행 결과

image

set,multiset에서 공부했던 것 처럼 원리는 똑같다 어려운 내용은 없다.




© 2022. by KSC

Powered by sora