C++ 초급 - 11. 표준 라이브러리(STL) (2 - std::map, std::unordered_map (연관 컨테이너))

2025. 2. 22. 17:39프로그래밍 언어/C++

📌 11.2 std::map, std::unordered_map (연관 컨테이너)

C++에서는 연관 컨테이너(Associative Container)를 사용하여 키-값 쌍을 저장하고 효율적으로 검색할 수 있다.
대표적인 연관 컨테이너로 std::map과 std::unordered_map이 있으며, 각각 이진 검색 트리 기반(정렬 저장)해시 기반(빠른 검색)의 차이가 있다.


📌 1. std::map (정렬된 키-값 쌍 저장)

🔹 (1) std::map이란?

  • 키(Key)에 대해 자동으로 정렬되는 연관 컨테이너.
  • 내부적으로 이진 검색 트리(Red-Black Tree)를 사용하여 데이터를 저장.
  • 시간 복잡도: 삽입, 삭제, 검색 연산이 O(log N).
  • 중복된 키를 허용하지 않음 (std::multimap은 중복 허용).

💡 기본 문법

#include <map>

std::map<int, std::string> myMap;  // 키: int, 값: string

💡 예제: std::map 기본 사용법

#include <iostream>
#include <map>

int main() {
    std::map<int, std::string> myMap;

    myMap[1] = "Apple";
    myMap[3] = "Banana";
    myMap[2] = "Cherry";

    std::cout << "키 2의 값: " << myMap[2] << std::endl;

    // 자동 정렬된 출력
    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

🔹 출력 결과

키 2의 값: Cherry
1: Apple
2: Cherry
3: Banana

💡 설명

  • std::map은 키를 자동으로 정렬 (1 → 2 → 3 순서로 저장됨).
  • myMap[2]는 해당 키의 값을 반환.

📌 2. std::unordered_map (해시 기반 빠른 검색)

🔹 (1) std::unordered_map이란?

  • 해시 테이블(Hash Table)을 기반으로 동작하는 연관 컨테이너.
  • 키의 정렬을 보장하지 않음.
  • 시간 복잡도: 평균 O(1), 최악의 경우 O(N).
  • 중복된 키를 허용하지 않음 (std::unordered_multimap은 중복 허용).

💡 기본 문법

#include <unordered_map>

std::unordered_map<int, std::string> myUnorderedMap;

💡 예제: std::unordered_map 기본 사용법

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, std::string> myUnorderedMap;

    myUnorderedMap[1] = "Apple";
    myUnorderedMap[3] = "Banana";
    myUnorderedMap[2] = "Cherry";

    std::cout << "키 2의 값: " << myUnorderedMap[2] << std::endl;

    // 무작위 순서로 출력
    for (const auto& pair : myUnorderedMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

🔹 출력 결과 (실행할 때마다 순서가 다를 수 있음)

키 2의 값: Cherry
3: Banana
1: Apple
2: Cherry

💡 설명

  • 해시 테이블 기반이므로 O(1)의 빠른 검색이 가능.
  • 입력 순서와 상관없이 무작위 순서로 저장됨.

📌 3. 삽입, 삭제, 탐색 (insert, erase, find)

🔹 (1) insert를 활용한 요소 추가

💡 예제: insert()를 사용한 요소 추가

#include <iostream>
#include <map>

int main() {
    std::map<int, std::string> myMap;
    
    myMap.insert({1, "Apple"});
    myMap.insert(std::make_pair(2, "Banana"));

    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

🔹 (2) erase를 활용한 요소 삭제

💡 예제: erase()를 사용한 요소 삭제

myMap.erase(1);  // 키 1 제거

🔹 (3) find를 활용한 탐색

💡 예제: find()를 사용한 요소 검색

auto it = myMap.find(2);
if (it != myMap.end()) {
    std::cout << "찾은 값: " << it->second << std::endl;
}

📌 4. std::map vs std::unordered_map 성능 차이

특징 std::map std::unordered_map
구조 이진 검색 트리(Red-Black Tree) 해시 테이블(Hash Table)
정렬 자동 정렬 O 정렬되지 않음 X
삽입, 삭제, 검색 O(log N) 평균 O(1), 최악 O(N)
메모리 사용량 상대적으로 적음 상대적으로 많음
적합한 경우 정렬된 데이터를 유지해야 하는 경우 빠른 검색이 필요한 경우

💡 선택 기준

  • 정렬된 데이터가 필요하면 std::map 사용.
  • 빠른 검색이 필요하면 std::unordered_map 사용.

📌 5. 커스텀 비교 함수 및 해시 함수 적용 방법

🔹 (1) std::map에서 사용자 정의 비교 함수 사용

  • 기본적으로 std::map은 operator<을 사용하여 정렬하지만, 사용자 정의 비교 함수를 사용할 수도 있다.

💡 예제: 내림차순 정렬

#include <iostream>
#include <map>

struct DescendingOrder {
    bool operator()(int a, int b) const {
        return a > b;  // 내림차순 정렬
    }
};

int main() {
    std::map<int, std::string, DescendingOrder> myMap;
    
    myMap[1] = "Apple";
    myMap[3] = "Banana";
    myMap[2] = "Cherry";

    for (const auto& pair : myMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

🔹 출력 결과

3: Banana
2: Cherry
1: Apple

🔹 (2) std::unordered_map에서 사용자 정의 해시 함수 사용

  • 기본적으로 std::unordered_map은 std::hash<T>를 사용하여 해싱하지만, 사용자 정의 해시 함수를 지정할 수도 있다.

💡 예제: 사용자 정의 해시 함수

#include <iostream>
#include <unordered_map>

struct CustomHash {
    size_t operator()(int x) const {
        return x % 10;  // 단순한 해시 함수
    }
};

int main() {
    std::unordered_map<int, std::string, CustomHash> myUnorderedMap;
    
    myUnorderedMap[1] = "Apple";
    myUnorderedMap[12] = "Banana";  // 같은 해시값을 가질 수 있음

    for (const auto& pair : myUnorderedMap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

📌 6. 정리

개념 설명
std::map 키가 정렬된 상태로 저장되는 연관 컨테이너
std::unordered_map 해시 기반으로 저장되어 빠른 검색 가능
삽입, 삭제, 탐색 insert, erase, find 활용
성능 차이 std::map → O(log N), std::unordered_map → 평균 O(1)
커스텀 정렬 및 해시 std::map은 사용자 정의 비교 함수 가능, std::unordered_map은 사용자 정의 해시 가능