• Home
  • About
    • 코드좀비 photo

      코드좀비

      An amazing website.

    • Learn More
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

C++ 셋(set) 과 멥(map) 종류, 쉽게 알아보자. (+멀티맵,멀티셋,unodred_set,multi_set)

16 May 2019

Reading time ~3 minutes

이번 포스팅은 앞으로도 셋,멥 관하여 쓸일이 종종 있을 거 같기에..

정리 하는겸, 저도 참고 하기 위해서 작성 하게 되었습니다.

우선 간단하게 SET 과 MAP 이 무엇인지 확인하고 넘어가볼께요

SET : 해당 데이터가 있나? 없나 확인 MAP : 해당 번호에 뭐가 들어있나?

SET


추가 방식

set<int> s;
s.insert(10);
s.insert(5);

데이터 있는지 확인하는 방법

auto itr = s.find(10);
itr == itr.end() <= 없음
itr != itr.end() <= 있음

전체 출력

for(auto itr = s.begin() ; itr != s.end(); itr++){
    cout << *itr
}

특징

  • 자동으로 정렬됨
  • 탐색시 O(LogN) 보장 ( 트리 형식으로 데이터를 저장합니다. 단순 트리보다는 보정이 있어서 한쪽으로 쏠리는걸 방지해줍니다.)
  • 중복을 허용하지 않습니다. ( 다만 insert 시 컴파일 환경에 따라서 자동으로 insert처리 안하는 곳이 있는 반면 이미 있는값을 insert 시 런타임 에러 나는 환경이 있을 수 있습니다. 중복값이 올 수 있다면 find 로 확인을 하고 넘어가야합니다.)

unordered_set


작동 방식

  • 기본적으로 사용 방법은 위의 SET과 완전히 동일합니다.
  • 다른점은 정렬을 해주지 않습니다. 해시를 사용하여 데이터 값이 순서대로 저장 되지 않습니다.
  • 해시를 사용하는 만큼 탐색시 O(1) 을 보장합니다. => 즉 데이터가 있는지 없는지만 판단 하려 한다면 unordered_set 이 제일 빠릅니다. => 반면 데이터의 추가,삽입 시 해시이기 때문에, 재해싱이 일어 날 수 있으며, 재해싱 하게 된다면 모든 데이터를 다시 복사 해서 옮겨야 하기 때문에 그 과정에서 O(N)의 시간이 소요됩니다. (즉 find = O(1) , insert = O(1) or O(N))

multi_set


작동 방식

  • 기본적으로 사용 방법은 위의 SET과 완전 동일 합니다.
  • 중복으로 값이 들어가는 것을 허용 해줍니다.

MAP


추가 방식

map<int,string> m;
m.insert(make_pair(1,"hi");  (혹은 m.insert(pair<int,string>(1,"hi")) 도 가능합니다. )
m.insert(make_pair(2,"gi");
m[3] = "oh!"   <= 이렇게도 추가가 가능합니다. 다만 권장 하지는 않습니다.

데이터 있는지 확인하는 방법

auto itr = m.find(1);
itr == itr.end <= 없음
itr != itr.end <= 있음

전체 출력

  • 첫값은 itr->first , 두번쨰 값은 itr->second
    for(auto itr = m.begin() ; itr != m.end(); itr++){
      cout << itr->first << " " << itr->second ;  
    }
    

특징

  • 자동으로 정렬됨
  • 탐색시 O(LogN) 보장 ( 트리 형식으로 데이터를 저장합니다. 단순 트리보다는 보정이 있어서 한쪽으로 쏠리는걸 방지해줍니다.)
  • 중복을 허용하지 않습니다. ( 다만 insert 시 컴파일 환경에 따라서 자동으로 insert처리 안하는 곳이 있는 반면 이미 있는값을 insert 시 런타임 에러 나는 환경이 있을 수 있습니다. 중복값이 올 수 있다면 find 로 확인을 하고 넘어가야합니다.)

# multi_map *** ## 작동 방식

  • 기본적으로 사용 방법읜 위의 SET과 거의 동일합니다.
  • 중복으로 값이 들어가는 것을 허용 해 줍니다.
  • 다만 set처럼 있는지 없는지가 아닌 Pair 형태임으로 탐색시 특별한 방법으로 탐색을 해야 합니다.
  • 위의 이유와 마찬가지로 [] 를 사용하여서 호출 할 수 없습니다.
  • sql기능 없이 두 표를 합하거나 할때 등 있으면 꼭 유용한 사항이 있기에 연습 해보시는걸 추천드립니다.

## 특정 데이터의 pair 값 찾기

 auto range = m.equal_range(1);
  for (auto itr = range.first; itr != range.second; ++itr) {
    cout << itr->first << " : " << itr->second << " " << endl;
  }
  • 위와 같이 행하면 range 는 새로운 pair<int,int> range 로 만들어지며, range->first 는 equal_range(x) 에서 x와 동일한 값의 처음을, range->second 는 equal_range(x) 에서 x 와 동일한 값의 마지막을 불러오게 됩니다.
     // 현재 m 에 들어있는 것 => (1,a), (2,b), (3,d), (3,f), (3,g), (4,h)
     auto range = m.equal_range(3)
     // range->first => (3,d) 가 저장된 위치, range->second = (3,g) 가 저장된 위치
    

# unordered_map *** ## 작동 방식

  • 기본적으로 사용 방법은 위의 MAP과 완전히 동일합니다.
  • 다른점은 정렬을 해주지 않습니다. 해시를 사용하여 데이터 값이 순서대로 저장 되지 않습니다.
  • 해시를 사용하는 만큼 탐색시 O(1) 을 보장합니다. => 즉 데이터가 있는지 없는지만 판단 하려 한다면 unordered_map 이 제일 빠릅니다. => 반면 데이터의 추가,삽입 시 해시이기 때문에, 재해싱이 일어 날 수 있으며, 재해싱 하게 된다면 모든 데이터를 다시 복사 해서 옮겨야 하기 때문에 그 과정에서 O(N)의 시간이 소요됩니다. (즉 find = O(1) , insert = O(1) or O(N))

개인적인 중요도 순서

  • map > set > multi_map > unodered_set = unodered_map = multi_set 이라고 생각 합니다. 범용성 기준으로 저의 주관적인 생각입니다. 뒤에 3개에 다 동일을 준 이유는 너무 특수한 상황에서만 쓰기 때문에 이렇게 점수를 줬습니다.


셋멥setmapmultimapmultisetunordered_setunordered_map멀티셋C++멀티맵 Share Tweet +1