什麼是 Unordered_map? Link to heading

std::unordered_map 是 C++11 引入的無序關聯容器,使用哈希表實現,提供平均 O(1) 的查找性能。

與其他容器的主要區別

  • map:unordered_map 無序(哈希表),map 有序(紅黑樹)
  • unordered_multimap:unordered_map 鍵唯一,unordered_multimap 允許重複鍵

適用場景

  • 需要快速查找、插入、刪除(O(1) 平均)
  • 不需要有序性
  • 鍵必須唯一
  • 鍵類型可以哈希

內部實現原理 Link to heading

底層數據結構 Link to heading

使用哈希表(Hash Table)實現,採用鏈式法(chaining)解決哈希衝突。

哈希表結構:
buckets:
[0] -> nullptr
[1] -> {key1, val1} -> {key7, val7} -> nullptr
[2] -> nullptr
[3] -> {key3, val3} -> nullptr
[4] -> {key4, val4} -> {key11, val11} -> nullptr
...

當 load_factor 超過閾值時,會進行 rehash(重新分配更大的桶陣列)

關鍵概念

  • 哈希函式:將鍵轉換為桶索引
  • 負載因子:元素數量 / 桶數量
  • Rehash:當負載因子過高時,擴展桶陣列

基本使用 Link to heading

#include <unordered_map>
#include <iostream>
#include <string>

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

    // 插入
    myMap["apple"] = 100;
    myMap.insert({"banana", 200});
    myMap.emplace("cherry", 300);

    // 訪問
    std::cout << "apple: " << myMap["apple"] << std::endl;
    std::cout << "banana: " << myMap.at("banana") << std::endl;

    // 查找
    if (myMap.find("cherry") != myMap.end()) {
        std::cout << "找到 cherry" << std::endl;
    }

    // 遍歷(無序)
    for (const auto& [key, value] : myMap) {
        std::cout << key << ": " << value << std::endl;
    }

    return 0;
}

性能分析 Link to heading

操作unordered_mapmap
查找O(1) 平均, O(n) 最壞O(log n)
插入O(1) 平均, O(n) 最壞O(log n)
刪除O(1) 平均, O(n) 最壞O(log n)
有序遍歷

常見陷阱 Link to heading

1. 自訂型別需要哈希函式 Link to heading

struct Point {
    int x, y;
};

// ❌ 錯誤:Point 沒有哈希函式
// std::unordered_map<Point, int> myMap;

// ✅ 解決方案:提供哈希函式
struct PointHash {
    size_t operator()(const Point& p) const {
        return std::hash<int>()(p.x) ^ (std::hash<int>()(p.y) << 1);
    }
};

struct PointEqual {
    bool operator()(const Point& a, const Point& b) const {
        return a.x == b.x && a.y == b.y;
    }
};

std::unordered_map<Point, int, PointHash, PointEqual> myMap;

2. 迭代器可能在 rehash 時失效 Link to heading

std::unordered_map<int, int> myMap = {{1, 1}, {2, 2}};
auto it = myMap.begin();

// 大量插入可能觸發 rehash
for (int i = 0; i < 1000; ++i) {
    myMap[i] = i;  // rehash 後 it 可能失效
}

// ⚠️ it 可能已失效

實際應用場景 Link to heading

字元頻率統計 Link to heading

#include <unordered_map>
#include <string>
#include <iostream>

std::unordered_map<char, int> countFrequency(const std::string& str) {
    std::unordered_map<char, int> freq;
    for (char c : str) {
        freq[c]++;
    }
    return freq;
}

int main() {
    std::string text = "hello world";
    auto freq = countFrequency(text);

    for (const auto& [ch, count] : freq) {
        std::cout << ch << ": " << count << std::endl;
    }

    return 0;
}

實務建議 Link to heading

DO(應該做的) Link to heading

使用 unordered_map 進行快速查找

// 快取查找
std::unordered_map<std::string, Result> cache;

使用 reserve 預留空間

std::unordered_map<int, int> myMap;
myMap.reserve(1000);  // 避免多次 rehash

DON’T(不應該做的) Link to heading

不要在需要有序遍歷時使用

// ❌ 錯誤:unordered_map 是無序的
std::unordered_map<int, int> myMap;
// 遍歷順序不確定

// ✅ 正確:使用 map
std::map<int, int> myMap;

小結 Link to heading

std::unordered_map 是基於哈希表的無序映射容器,提供平均 O(1) 的插入、刪除、查找性能,適合需要快速查找且不需要有序性的場景。