[C++] 맵(Map)

👻 맵(Map)

맵(Map)은 시퀀스 컨테이너가 아닌 연관 컨테이너에 속하는 요소이다. 맵은 균형 이진 트리(AVL)의 자료구조로 만들어져있다. 벡터와 리스트로는 원하는 조건에 해당하는 데이터를 빠르게 찾을 수 없다. 이러한 단점을 보완하기 위해 나온 것이 맵이다. 맵 또한 리스트와 같은 노드 기반으로 만들어졌다.

  • 균형 이진 트리(AVL)
    Alt Text
#include <map>

map<int, int> m;

// 노드 기반
class Node {
  public:
  Node* _left;
  Node* _right;
  // DATA
  pair<int, Player*> _data;
  // int _key;
  // Player* _value;
}

map 라이브러리를 사용해야하고 다른 STL 문법과 비슷하게 작성한다. 대신에 꺽쇠 내의 타입은 각각 keyvalue의 타입을 의미한다.


🌱 맵의 삽입과 삭제

다른 문법과 비슷하게 insert, erase로 데이터를 삽입, 삭제할 수 있다. 단, 키(Key)고유한 값을 가진다.

// insert 두 번 해보기 : 같은 키 값으로 추가할 순 없다. 두 번째 추가되는 코드가 무시된다.
pair<map<int, int>::iterator, bool> ok;
ok = m.insert(make_pair(1, 100));
ok = m.insert(make_pair(1, 200));

// erase 두 번 해보기 : 이미 삭제되면 두 번째 코드는 무시된다.
unsigned int count = m.erase(10000);
count = m.erase(10000);

insert는 삽입된 데이터의 이터레이터와 삽입 여부를 반환한다. 키는 고유한 값을 가지기 때문에 동일한 키로 데이터를 중복 삽입하게되면 첫 번째 이후의 삽입문은 무시되고 false를 반환한다.

erase는 삭제된 횟수를 반환한다. 마찬가지로 이미 삭제한 데이터를 또다시 삭제하게 되면 첫 번째 이후의 삭제문은 무시되고 삭제 횟수는 0을 반환한다. 성공적으로 삭제하면 1을 반환한다.


🌱 맵의 조회와 순회

  • 조회
    맵에서 키 값을 이용해 데이터를 가져올 수 있다. find 함수를 사용한다.
// m.find([Key]);
m.find(10000);

맵의 이터레이터를 반환하게되며, 만약 찾지 못한 경우 end() 값을 반환한다.

  • 순회
    이터레이터를 활용해야한다.
for (map<int, int>::iterator it = m.begin(); it != m.end(); ++it) {
  pair<const int, int>& p = (*it);
  int key = p.first;
  int value = p.second;

  cout << key << " " << value << endl;
}

해당 이터레이터의 반환 타입은 pair이다. 각각 firstsecond로 접근할 수 있다.


🌱 [] 연산자

위에서 알아본 함수들을 조합하여 맵에 간편하게 데이터를 추가, 수정할 수 있다. 키 값을 이용하여 접근한 뒤 해당 데이터가 없으면 추가를, 이미 존재하면 수정이 진행된다.

map<int, int>::iterator findIt2 = m.find(10000);
if (findIt != m.end()) findIt->second = 200;
else m.insert(make_pair(10000, 200));

조건문을 이용해 매번 확인하고 추가, 수정하기 귀찮다면 [] 연산자를 이용하여 훨씬 간편하게 데이터에 접근할 수 있다.

m[10000] = 200;

위의 코드는 키가 10000인 데이터가 있는 경우 200으로 수정을 해주지만, 만약 데이터가 없을 경우 키 값은 10000, 데이터는 200인 맵이 새로 추가된다는 뜻이다.

💡 [] 사용 시 주의할 점
👉 만약 해당 키 값을 가지는 데이터가 없을 경우, 따로 대입을 하지 않더라도 Key/Value 형태의 데이터가 추가된다.

for (int i = 0; i < 10; i++)
  cout << m[i] << endl;

위의 코드에서 맵에 아무런 데이터도 없다고 가정할 때, 따로 대입 연산자를 사용하진 않았지만 데이터는 0으로 초기화되어 Key/Value 형태의 데이터가 맵에 새로 추가된다.


👻 글을 마치며

이번 시간에는 맵에 대해 알아보았다. 배열에 이어 개인적으로도 또 좋아하는 타입이다. 그래서 재미있게 공부할 수 있었고 약간 속성으로 배울 때는 여러 문법의 개념이 확실하게 잡히지 않아 어쩔 땐 .을 쓰고 어쩔 땐 화살표를 써야할지 몰랐다. 이제 맵까지 배운 지금 포인터가 점차 익숙해지면서 언제 어디서 어떤 기호를 써야할지 감이 잡히기 시작하는 것 같다.


소스코드 보러가기


출처
인프런 Rookies님 강의

Categories:

Updated:

Leave a comment