오늘의 주제: std::map

c++ 에서 std::map 은 컨테이너로서 vector,list,deque 와 같은것이다. 하지만 map과 set 은 연관컨테이너로서 key와 value 를 함께 저장하고 자료구조형으로써 레드-블랙 트리를 사용하여 항상 key값을 기준으로 오름차순 정렬을 한다. 즉 특정 key와 value 를 입력하게 되면 key를 기준으로 재정렬을 하게된다. 이와 같은 방식으로 저장을 하게되면 특정 key에 대한 value를 찾고자 할 때 탐색속도는 tree 의 높이인 log(n)이 될 것이다. 따라서 stl 의 std::map 컨테이너를 잘 사용하면 손쉽게 자료를 정리할 수 있을 것이다.
그렇다면 어떻게 std::map 을 사용할 수 있는지에 대해서 예제를 통해 공부해 보고자 한다.

#include <iostream>
#include <map>

using namespace std;

int main(int argc, char const *argv[])
{
  map<string,int> name_score;
  pair<map<string,int>::iterator,bool> iter_bool_0 = name_score.insert(pair<string,int>("Aoi",100));
  pair<map<string,int>::iterator,bool> iter_bool_1 = name_score.insert(pair<string,int>("Aoi",90));
  pair<map<string,int>::iterator,bool> iter_bool_2 = name_score.insert(pair<string,int>("Sora",100));

  cout<< (iter_bool_0.second == true ? "true" : "false" )<<endl;
  cout<< (iter_bool_1.second == true ? "true" : "false" )<<endl;
  cout<< (iter_bool_2.second == true ? "true" : "false" )<<endl;

  name_score["Sora"] = 90;
  name_score["ZZang"] = 20;
  name_score["ZZang"] += 20;

  cout<<"total size of name_score is "<<name_score.size()<<endl;
  for(auto i : name_score)
  {
    cout<<i.first<<" : "<<i.second<<endl;
  }
  
  return 0;
}

다음의 예제는 map 컨테이너에 어떻게 값을 넣을 수 있는지에 대한 예제이다. 이 예제를 살펴보고 실제로 실행시켜보면 그 값이

true
false
true
total size of name_score is 3
Aoi : 100
Sora : 90
ZZang : 40

과 같이 나오게 된다. 즉 이 의미는 map::insert함수를 사용하여 key,value 를 넣는다면 중복되는 key에 대해서는 return 으로 false 를 뱉어주며 insert하지 않는다. 반면 map::[] 오퍼레이터 같은 경우는 key값에 해당하는 자료가 이미 있더라도 그를 수정하게 된다.
따라서 key값의 중복이 원하는 결과가 아니고 이를 절대적으로 막아야한다면 insert 함수의 return 을 이용하면 된다. 주의할점은 return의 타입이
pair<map<해당 map의 변수타입>,bool>이며 auto를 사용할 수 없다는 점이다.
만약 이러한 중복이 중요하지 않은 경우라면 [] 를 사용하면 될 것이다.

지금까지는 map 의 key와 value 를 넣는 것에 대해서 다루었고 사용은 key value에 접근하기, key에 해당하는 데이터 지우기, 이터레이터, key에 해당하는 데이터의 갯수를 세는 count, find 등이 있을 수 있다. 이에 대한 코드를 첨부하여 설명을 대체 하도록한다.

  //접근
  int sora_value = name_score["Sora"];
  //찾기, return값은 iterator
  map<string,int>::iterator iterator_ = name_score.find("ZZang");
  //갯수세기, key값에 해당하는 데이터의 갯수를 센다.(multimap 에서 유용할듯 하다.)
  name_score.count("Sora");

std::multimap 이란?

std::multimap은 다른게 아니라 map의 다른 버젼이다. 똑같이 key,value의 pair를 저장하며 key값을 기준으로 정렬되어있는 트리 구조라고 할 수 있다. 하지만 multimap 은 key값의 중복을 허락한다. 따라서 multimap을 사용하고자 할 때는 [] 오퍼레이터가 지원되지 않는다. 따라서 insert로 입력하며 접근 또한 find 를 이용하여 iterator 로 접근해야하며 key값에 해당하는 데이터의 갯수를 구하는 count함수를 이용해 접근을 할 수 있다.
사용법은 거의 동일하며 이는 여기서 다루지는 않도록하겠다.

오늘은 std::map에 대해서 다루어 보았다. std::map 은 c++11 부터 지원이 되기때문에 g++을 이용해 컴파일 하는 경우 warning message 가 나오므로 컴파일러 옵션을 설정해 주어야한다.
결국 map은 특정 데이터를 다루기에 적합한 stl 컨테이너로서 이를 잘 활용하여 코드를 구현하면 좋을듯 하다.