Posted Updated

C++ STL의 unordered_map은 Key-Value 형태의 데이터를 해시 기반으로 저장하는 연관 컨테이너 이다. 이전 포스팅에서 살펴본 map과 기능적으로는 유사하지만, 정렬을 하지 않고 속도에 집중한 컨테이너 라는 점이 가장 큰 차이이다.

std::unordered_map은 내부적으로 해시 테이블 을 사용한다.

특징

  • Key 중복 X
  • 정렬 X
  • 삽입/삭제/탐색: O(1)
  • 최악의 경우: O(n) (해시 충돌이 심한 경우)

속도는 빠르지만, 순서가 필요하면 사용하면 안 된다.

unordered_map의 헤더와 선언

#include <unordered_map>

unordered_map<int, string> um;

주요 멤버 함수

함수명 설명
insert({k, v}) (k, v) 쌍을 삽입
um[k] k에 해당하는 value 접근
find(k) key k를 가리키는 iterator 반환
erase(k) key k에 해당하는 원소 삭제
size() 저장된 원소 개수 반환
empty() 비어 있는지 확인

map과 인터페이스는 거의 동일하다.

예시 코드

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

int main() {
    unordered_map<int, string> um;

    um.insert({1, "apple"});
    um.insert({3, "banana"});
    um.insert({2, "orange"});

    for (auto p : um) {
        cout << p.first << ": " << p.second << "\n";
    }

    return 0;
}

🔽 출력 :

2: orange
3: banana
1: apple

출력 순서는 보장되지 않는다.

operator[] 사용 시 주의점

unordered_map에서도 operator[]는 존재하지 않는 key를 자동 생성한다.

unordered_map<int, int> um;

cout << um[5]; // 0 (자동 삽입)

따라서 map과 마찬가지로 단순 조회 목적인 경우에는 find()를 사용하는 것이 좋지만, 이는 map의 크기가 커지는 원인이 되기도 한다.

unordered_map이 빠른 이유

map은 트리 기반(O(logn))인 반면, unordered_map은 해시 기반(O(1))이다. Key를 해시 함수에 넣어 바로 버킷 위치를 계산하기 때문에 트리를 타고 내려갈 필요가 없다.

다만 여러 Key가 같은 해시 값을 가질 때 해시 충돌이 발생할 수 있다. 충돌이 많아지면 성능이 저하되며, 최악의 경우 O(n) 시간 복잡도를 보이지만 STL의 기본 해시 함수는 대부분의 상황에서 충분히 안정적이다.

map과 unordered_map 정리

항목 map unordered_map
내부 구조 트리 해시 테이블
정렬 여부 O (Key 기준 자동 정렬) X
탐색 속도 O(logn) 평균 O(1)
순회 순서 Key 오름차순으로 보장됨 보장되지 않음
범위 탐색 가능 불가능

unordered_map은 언제 쓰일까?

  • 정렬이 전혀 필요 없을 때
  • 빠른 삽입/탐색이 중요한 경우
  • 빈도 카운트, 존재 여부 체크 등

마무리

unordered_map은 속도 최우선 컨테이너이다. 평균 O(1)의 빠른 연산을 보여주며, 순서가 필요하면 map, 속도가 중요하면 unordered_map을 사용하면 된다.

Leave a comment