目录

  1. 概述
  2. 基本特性
  3. 基本用法
  1. <map> 的对比
  2. 注意事项
  3. 实用示例:单词计数器
  4. 小练习
  1. 参考资料
  2. 出站链接

概述

<unordered_map> 是 C++ STL 中的无序关联容器,用于存储键值对(key-value pairs)。它基于哈希表实现,键是唯一的,元素不按任何顺序排列。相比 <map>,它提供更快的平均查找性能,但牺牲了排序功能。

包含头文件

#include <unordered_map>
#include <iostream>

定义格式

std::unordered_map<键类型, 值类型, 哈希函数, 相等比较器> 变量名;
  • 键类型:键的数据类型(如 intstd::string)。
  • 值类型:值的数据类型(如 intdouble)。
  • 哈希函数:可选,默认是 std::hash<Key>
  • 相等比较器:可选,默认是 std::equal_to<Key>

基本特性

  • 键唯一性:每个键只能对应一个值。
  • 无序存储:键值对不按任何顺序排列。
  • 高效操作:平均时间复杂度 O(1)(插入、删除、查找),最坏 O(n)(哈希冲突时)。
  • 动态大小:支持运行时调整。

基本用法

声明和初始化

#include <unordered_map>
#include <iostream>

int main() {
    std::unordered_map<int, std::string> um;             // 空 unordered_map
    std::unordered_map<int, std::string> um2 = {{1, "A"}, {2, "B"}, {3, "C"}}; // 初始化列表(C++11)

    std::cout << "um2: ";
    for (const auto& pair : um2) {
        std::cout << "{" << pair.first << ", " << pair.second << "} ";
    }
    std::cout << std::endl; // 输出顺序不定,如:{3, C} {1, A} {2, B}
    return 0;
}

插入元素

#include <unordered_map>
#include <iostream>

int main() {
    std::unordered_map<int, std::string> um;
    um.insert({1, "Alice"});          // 插入键值对
    um.insert(std::make_pair(2, "Bob"));
    um[3] = "Charlie";                // 使用 [] 插入或覆盖

    std::cout << "um: ";
    for (const auto& pair : um) {
        std::cout << "{" << pair.first << ", " << pair.second << "} ";
    }
    std::cout << std::endl; // 输出顺序不定,如:{2, Bob} {3, Charlie} {1, Alice}
    return 0;
}

删除元素

#include <unordered_map>
#include <iostream>

int main() {
    std::unordered_map<int, std::string> um = {{1, "A"}, {2, "B"}, {3, "C"}};
    um.erase(2); // 删除键为 2 的元素

    std::cout << "After erase: ";
    for (const auto& pair : um) {
        std::cout << "{" << pair.first << ", " << pair.second << "} ";
    }
    std::cout << std::endl; // 输出顺序不定,如:{1, A} {3, C}
    return 0;
}

查找元素

#include <unordered_map>
#include <iostream>

int main() {
    std::unordered_map<int, std::string> um = {{1, "A"}, {2, "B"}, {3, "C"}};
    auto it = um.find(2); // 查找键为 2 的元素
    if (it != um.end()) {
        std::cout << "Found: {" << it->first << ", " << it->second << "}" << std::endl; // 输出:Found: {2, B}
    }

    if (um.count(1)) {
        std::cout << "Key 1 exists" << std::endl; // 输出:Key 1 exists
    }
    return 0;
}

访问和修改元素

#include <unordered_map>
#include <iostream>

int main() {
    std::unordered_map<int, std::string> um = {{1, "A"}, {2, "B"}};
    std::cout << "Value at 1: " << um[1] << std::endl; // 输出:A
    um[1] = "Alice"; // 修改值
    std::cout << "New value at 1: " << um.at(1) << std::endl; // 输出:Alice

    // um.at(3) 若键不存在会抛出 std::out_of_range
    return 0;
}
  • []:若键不存在,插入默认值。
  • at():若键不存在,抛异常。

大小和状态

#include <unordered_map>
#include <iostream>

int main() {
    std::unordered_map<int, std::string> um = {{1, "A"}, {2, "B"}};
    std::cout << "Size: " << um.size() << std::endl;         // 输出:2
    std::cout << "Empty? " << (um.empty() ? "Yes" : "No") << std::endl; // 输出:No
    return 0;
}

哈希表特性

#include <unordered_map>
#include <iostream>

int main() {
    std::unordered_map<int, std::string> um = {{1, "A"}, {2, "B"}, {3, "C"}};
    std::cout << "Bucket count: " << um.bucket_count() << std::endl; // 桶数
    std::cout << "Load factor: " << um.load_factor() << std::endl;   // 当前负载因子
    std::cout << "Max load factor: " << um.max_load_factor() << std::endl; // 最大负载因子
    return 0;
}

迭代器

#include <unordered_map>
#include <iostream>

int main() {
    std::unordered_map<int, std::string> um = {{1, "A"}, {2, "B"}, {3, "C"}};
    std::cout << "Elements: ";
    for (auto it = um.begin(); it != um.end(); ++it) {
        std::cout << "{" << it->first << ", " << it->second << "} ";
    }
    std::cout << std::endl; // 输出顺序不定,如:{3, C} {1, A} {2, B}
    return 0;
}
  • 仅支持前向迭代器,无逆向迭代。

<map> 的对比

特性std::unordered_mapstd::map
数据结构哈希表平衡二叉树
键顺序无序升序
重复键不允许不允许
查找平均 O(1)O(log n)
插入/删除平均 O(1)O(log n)
内存开销桶+指针树节点+指针
迭代器前向双向

注意事项

  1. 哈希冲突:冲突严重时性能退化为 O(n),需优化哈希函数。
  2. 迭代器失效:插入不影响现有迭代器,删除使指向被删元素的迭代器失效。
  3. 自定义键类型:需提供哈希函数和相等比较器。
  4. [] 的副作用:访问不存在的键会插入默认值。

自定义键类型示例

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

struct CustomKey {
    std::string name;
    int id;
    bool operator==(const CustomKey& other) const {
        return name == other.name && id == other.id;
    }
};

namespace std {
    template<> struct hash<CustomKey> {
        size_t operator()(const CustomKey& k) const {
            return hash<string>()(k.name) ^ hash<int>()(k.id);
        }
    };
}

int main() {
    std::unordered_map<CustomKey, int> um;
    um[{"Alice", 1}] = 95;
    um[{"Bob", 2}] = 87;

    for (const auto& pair : um) {
        std::cout << "{" << pair.first.name << ", " << pair.first.id << "}: " << pair.second << "\n";
    }
    return 0;
}

实用示例:单词计数器

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

int main() {
    std::unordered_map<std::string, int> wordCount;
    std::string word;
    std::cout << "Enter words (Ctrl+D or Ctrl+Z to stop):\n";
    while (std::cin >> word) {
        wordCount[word]++;
    }

    std::cout << "Word frequencies:\n";
    for (const auto& pair : wordCount) {
        std::cout << pair.first << ": " << pair.second << "\n";
    }
    return 0;
}

输入示例:

apple banana apple cherry
Ctrl+D

输出(顺序不定):

Word frequencies:
apple: 2
banana: 1
cherry: 1

小练习

问题

写一个 C++ 程序:

  1. 定义一个 std::unordered_map<int, std::string>
  2. 插入键值对:{1, “A”}、{2, “B”}、{3, “C”}、{2, “D”}(注意重复键)。
  3. 删除键为 1 的元素。
  4. 输出所有键值对和大小。

参考答案

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

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

    // 插入元素
    um.insert({1, "A"});
    um.insert({2, "B"});
    um.insert({3, "C"});
    um[2] = "D"; // 覆盖键 2 的值

    // 删除键 1
    um.erase(1);

    // 输出所有键值对和大小
    std::cout << "Elements: ";
    for (const auto& pair : um) {
        std::cout << "{" << pair.first << ", " << pair.second << "} ";
    }
    std::cout << "\nSize: " << um.size() << std::endl;

    return 0;
}

输出(顺序不定):

Elements: {2, D} {3, C}
Size: 2

参考资料

  1. C++ Standard Library Reference: <unordered_map> 的官方文档。
  • ISO/IEC 14882:2011 (C++11 Standard)
  1. cppreference.com: 提供 <unordered_map> 的详细说明和示例。
  2. The C++ Programming Language (4th Edition) by Bjarne Stroustrup: C++ 容器权威书籍。
  3. Effective STL by Scott Meyers: STL 容器实用建议。

出站链接


下一步

  • 如果你想试试练习,请提交代码,我会帮你检查。
  • 如果需要更深入内容(如自定义哈希优化、与 <unordered_multimap> 对比),或设计测验题,请告诉我!
  • 你也可以提出具体问题,如“如何用 <unordered_map> 实现缓存?”或“<unordered_map> 的哈希表实现细节?”。

现在,你想做什么?试试练习,还是有其他需求?