C++

STL - map

팀(Tim) 2020. 10. 27. 02:14

 

표준 연관 컨테이너 (비선형적)

트리구조이다.

 

map은 key와 value를 한 쌍으로 가진다.

 

map<int, int> myMap;

 

인덱스를 통해 접근이 가능하다.

 

myMap[1]



원소 삽입

map은 원소삽입시 key와 value를 직접적으로 전달 할 수 없고,

pair라는 객체를 전달해야한다.

 

방법1

- myMap.insert(pair<int, int>(3,5))

 

방법2

- myMap.insert(make_pair(3,5))

 

방법3

-myMap.insert(map<int, int>::value_type(3,5)) // key는 저절로 const가 됨

 

방법4

- myMap[1] = 100; // 1이라는 키가 없을 경우 생성하고, 있을경우 value를 '수정'한다.

-> 맵의 키를 탐색하기 때문에 시간이 오래걸린다. '수정'하기 때문에 예상치 못한 동작을 할 수 있다.

(insert를 통한 삽입은 key가 없으면 추가하고, 있으면 '무시'한다.)

 

방법5

- myMap.emplace(3,5);

 

방법6

유니폼 초기화

- myMap.insert({3,5})

 

 

중간 삽입

의미없다. 원소 삽입시 자동 정렬되기 때문에.

 

 

중간 삭제

노드 기반 컨테이너이므로 중간 삭제를 하여도 end가 무효화되지 않는다.

 

 

반복자

양방향 반복자다. 즉, ++ 과 --만 가능.

*iter의 결과는 pair객체다. 따라서 (*iter).first처럼 하거나  

iter->first 이런식으로 키값조회 가능.

 

정렬

맵은 디폴트로 오름차순 정렬이다.

내림차순으로 정렬하고 싶으면 조건자를 쓰면 된다.

map<int, int, greater<int>> myMap;

 

탐색

find의 인자로 key값을 주면 해당 위치의 반복자를 반환한다.

만약 없을경우, end를 반환한다.

map<int, int>::iterator iter = myMap.find(3);

 

map에 key를 문자열로할 경우

myMap.insert(map<char*, int>::value_type("AAA", 100));

 

-> char*형이므로 그저 주소값이다. 따라서 또다시

 

myMap.insert(map<char*, int>::value_type("AAA", 100));

 

이렇게해도 가능하다. 주소값은 다르기 때문이다.

이런 것을 막기 위해 알고리즘 함수인 find_if를 쓴다.

 

auto& iter = find_if(myMap.begin(), myMap.end(), CStringCmp("AAA"));

 

if(iter != MyMap.end())

    cout << iter->first << ", " << iter->second << endl;

이렇게 조건자를 정의해주고 넣으면 문자열비교로 찾는게 가능하다.



class CStringCmp

{

public:

    CStringCmp(const char* _strKey) : m_strKey(_strKey) {}



public:

    template <typename T>

    bool operator()(T& _Dst)

    {

        return !strcmp(m_strKey, _Dst.first);

    }



private:

    const char* m_strKey;

};

 

-> find_if의 조건자는 단항 조건자이므로 인자 하나를 받는 함수객체로 정의해야한다.

operator의 _Dst는 find_if함수에서 맵을 순회하며 원소를 하나하나 인자로 넣는 식으로 알아서 호출해준다.

 

-> 귀찮으니까 그냥 string을 쓰도록하자. string은 비교연산자가 정의되어있어서 이럴 필요가 없다.