好的!以下是关于 C++ 容器类 <unordered_set> 的完整讲解,我已添加目录、参考资料和出站链接。为了保持结构清晰,我会基于之前的回答进行整理,并在文末添加你请求的内容。如果你需要对其他容器类(如 <set><vector> 等)也加上类似结构,请告诉我!


C++ 容器类 <unordered_set> 详解

目录

  1. 概述
  2. 基本特性
  3. 基本用法
  1. <set> 的对比
  2. 注意事项
  3. 自定义类型示例
  4. 实用示例:统计唯一访问者
  5. 小练习
  1. 参考资料
  2. 出站链接

概述

<unordered_set> 是 C++11 引入的标准库容器,基于哈希表实现,用于存储无序的唯一元素。它提供平均 O(1) 的插入、删除和查找操作,适用于需要高效查询的场景。

包含头文件

#include <unordered_set>
#include <iostream>

定义格式

std::unordered_set<类型, 哈希函数, 相等比较器> 变量名;

基本特性

  • 无序存储:元素不按任何顺序排列。
  • 唯一性:不允许重复元素。
  • 高效操作:平均时间复杂度 O(1),最坏 O(n)(哈希冲突时)。
  • 动态大小:支持运行时调整。

基本用法

声明和初始化

#include <unordered_set>
#include <iostream>

int main() {
    std::unordered_set<int> us;             // 空无序集合
    std::unordered_set<int> us2 = {1, 2, 3, 4, 2}; // 初始化列表,重复的 2 被忽略

    std::cout << "us2: ";
    for (int val : us2) {
        std::cout << val << " "; // 输出顺序不定,如:4 3 1 2
    }
    std::cout << std::endl;
    return 0;
}

插入元素

#include <unordered_set>
#include <iostream>

int main() {
    std::unordered_set<int> us;
    us.insert(10);
    us.insert(30);
    us.insert(20);
    us.insert(10); // 重复无效

    std::cout << "us: ";
    for (int val : us) {
        std::cout << val << " "; // 输出顺序不定,如:20 30 10
    }
    std::cout << std::endl;
    return 0;
}

删除元素

#include <unordered_set>
#include <iostream>

int main() {
    std::unordered_set<int> us = {1, 2, 3, 4};
    us.erase(2); // 删除值为 2

    std::cout << "After erase: ";
    for (int val : us) {
        std::cout << val << " "; // 输出顺序不定,如:4 3 1
    }
    std::cout << std::endl;
    return 0;
}

查找元素

#include <unordered_set>
#include <iostream>

int main() {
    std::unordered_set<int> us = {10, 20, 30};
    auto it = us.find(20);
    if (it != us.end()) {
        std::cout << "Found: " << *it << std::endl; // 输出:Found: 20
    }

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

大小和状态

#include <unordered_set>
#include <iostream>

int main() {
    std::unordered_set<int> us = {1, 2, 3};
    std::cout << "Size: " << us.size() << std::endl;         // 输出:3
    std::cout << "Empty? " << (us.empty() ? "Yes" : "No") << std::endl; // 输出:No
    return 0;
}

哈希表特性

#include <unordered_set>
#include <iostream>

int main() {
    std::unordered_set<int> us = {1, 2, 3, 4, 5};
    std::cout << "Bucket count: " << us.bucket_count() << std::endl;
    std::cout << "Load factor: " << us.load_factor() << std::endl;
    std::cout << "Max load factor: " << us.max_load_factor() << std::endl;
    return 0;
}

迭代器

#include <unordered_set>
#include <iostream>

int main() {
    std::unordered_set<std::string> us = {"Apple", "Banana", "Cherry"};
    std::cout << "Elements: ";
    for (auto it = us.begin(); it != us.end(); ++it) {
        std::cout << *it << " "; // 输出顺序不定,如:Cherry Apple Banana
    }
    std::cout << std::endl;
    return 0;
}

<set> 的对比

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

注意事项

  1. 哈希冲突:冲突严重时性能退化,需优化哈希函数。
  2. 迭代器失效:插入不影响现有迭代器,删除使指向被删元素的迭代器失效。
  3. 自定义类型:需提供哈希函数和相等比较器。
  4. 无排序:若需排序,使用 <set>

自定义类型示例

#include <unordered_set>
#include <iostream>
#include <string>

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

namespace std {
    template<> struct hash<Person> {
        size_t operator()(const Person& p) const {
            return hash<string>()(p.name) ^ hash<int>()(p.age);
        }
    };
}

int main() {
    std::unordered_set<Person> us;
    us.insert({"Alice", 25});
    us.insert({"Bob", 30});
    us.insert({"Alice", 25}); // 重复无效

    for (const Person& p : us) {
        std::cout << p.name << ", " << p.age << "\n";
    }
    return 0;
}

实用示例:统计唯一访问者

#include <unordered_set>
#include <iostream>
#include <string>

int main() {
    std::unordered_set<std::string> visitors;
    std::string id;
    std::cout << "Enter visitor IDs (Ctrl+D or Ctrl+Z to stop):\n";
    while (std::cin >> id) {
        visitors.insert(id);
    }

    std::cout << "Unique visitors: " << visitors.size() << "\n";
    return 0;
}

小练习

问题

写一个 C++ 程序:

  1. 定义一个 std::unordered_set<int>
  2. 插入 10、20、30、20、40(注意重复)。
  3. 删除值为 20 的元素。
  4. 输出所有元素和大小。

参考答案

#include <unordered_set>
#include <iostream>

int main() {
    std::unordered_set<int> us;

    us.insert(10);
    us.insert(20);
    us.insert(30);
    us.insert(20); // 重复无效
    us.insert(40);

    us.erase(20);

    std::cout << "Elements: ";
    for (int val : us) {
        std::cout << val << " ";
    }
    std::cout << "\nSize: " << us.size() << std::endl;

    return 0;
}

输出(顺序不定):

Elements: 40 10 30
Size: 3

参考资料

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

出站链接


下一步

  • 如果你想试试练习,请提交代码,我会帮你检查。
  • 如果需要更深入内容(如哈希表优化、与 <unordered_multiset> 对比),或设计测验题,请告诉我!
  • 你也可以提出具体问题,如“如何调整 <unordered_set> 的负载因子?”或“<unordered_set> 的哈希实现原理?”。

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