当前位置: 首页 > news >正文

std::unordered_set(C++)

std::unorderd_set

  • 1. 概述
    • 定义
    • 特点
  • 2. 内部实现
  • 3. 性能特征
  • 4. 常用 API
  • 5. 使用示例
  • 6. 自定义哈希与比较
  • 7. 注意事项与优化
  • 8. 使用建议

1. 概述

定义

template<class Key,class Hash = std::hash<Key>,class KeyEqual = std::equal_to<Key>,class Allocator = std::allocator<Key>
>
class std::unordered_set;

特点

  • 哈希表:基于哈希表实现,平均具有 O(1) 的查找、插入和删除效率。
  • 无序:元素在桶(bucket)中按哈希值分布,不保证遍历顺序。
  • 唯一:集合中不允许重复元素;插入已存在的键,不会改变容器状态。

2. 内部实现

  1. 桶与冲突解决

    • 容器维护若干桶,每个桶内用链表(或单链/双链)存放哈希冲突的元素。
    • 元素落桶位置:bucket_index = hash(key) % bucket_count。
  2. 装载因子(load factor)

    • 定义:load_factor = size() / bucket_count。
    • 达到或超过 max_load_factor() 时,自动 rehash(扩容并重新分布)。
  3. 再哈希(rehash)与保留(reserve)

    • rehash(n):将桶数至少调整为 n,并重分配元素。
    • reserve(n):保证能存放 n 个元素而不触发自动 rehash。

3. 性能特征

操作平均复杂度最坏情况复杂度说明
findO(1)O(n)当所有元素落入同一桶时退化为链表扫描
insertO(1)O(n)可能触发 rehash(O(n))
erase(key)O(1)O(n)同上
clearO(n)O(n)
遍历O(n + b)O(n + b)b = bucket_count;需跳过空桶
  • 空间开销:
    • 每个桶存储一个指针(头结点);每个元素节点存储键值与下一个节点指针。
  • 哈希函数质量:
    • 优质哈希函数能减少冲突,提升最坏情况表现;可针对自定义类型提供专业哈希。

4. 常用 API

// 构造与析构
std::unordered_set<Key> s1;                          // 默认构造
std::unordered_set<Key> s2(100);                     // 指定初始桶数
std::unordered_set<Key> s3(100, MyHash{});           // 指定哈希函数
std::unordered_set<Key> s4(100, MyHash{}, MyEqual{});// 指定哈希与相等比较// 大小与容量
bool empty() const noexcept;
size_t size() const noexcept;
size_t bucket_count() const noexcept;
float load_factor() const noexcept;
float max_load_factor() const noexcept;
void rehash(size_t n);
void reserve(size_t n);// 插入
std::pair<iterator,bool> insert(const Key& key);
template<class... Args>
std::pair<iterator,bool> emplace(Args&&... args);// 查找与删除
iterator find(const Key& key);
size_t erase(const Key& key);
void clear();// 遍历
iterator begin() noexcept;
iterator end() noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;// 桶信息
size_t bucket(const Key& key) const noexcept;
size_t bucket_size(size_t n) const noexcept;
Hash hash_function() const noexcept;
KeyEqual key_eq() const noexcept;

5. 使用示例

#include <unordered_set>
#include <string>
#include <iostream>int main() {// 1. 创建并插入std::unordered_set<std::string> us;us.insert("apple");us.insert(std::string("banana"));us.emplace("cherry");  // 2. 查找if (us.find("banana") != us.end()) {std::cout << "Found banana\n";}// 3. 遍历(无序)for (auto& s : us) {std::cout << s << "\n";}// 4. 预分配桶数us.reserve(1000);  // 预计要插入 1000 个元素,减少 rehash// 5. 输出装载因子std::cout << "Load factor: " << us.load_factor() << "\n";return 0;
}

6. 自定义哈希与比较

对于自定义类型,需提供哈希函数和相等比较:

struct Point { int x, y; };// 自定义哈希:结合位运算
struct PointHash {size_t operator()(Point const& p) const noexcept {return std::hash<int>()(p.x) ^ (std::hash<int>()(p.y) << 1);}
};// 自定义相等比较
struct PointEqual {bool operator()(Point const& a, Point const& b) const noexcept {return a.x == b.x && a.y == b.y;}
};std::unordered_set<Point, PointHash, PointEqual> pts;

7. 注意事项与优化

  1. 避免频繁 rehash

    • 通过 reserve(n) 预先分配,避免多次自动扩容带来的性能抖动。
  2. 遍历顺序不稳定

    • 迭代顺序可能因 rehash 而变化,不要依赖元素插入或桶索引顺序。
  3. 哈希安全

    • 对抗恶意输入可使用带随机种子或高质量哈希(如 MurmurHash、CityHash)。
  4. 线程安全

    • 并发读一般安全;读写或多写需自行加锁。
  5. 内存 vs 性能

    • 哈希表占用内存高于平衡树;在对空间敏感场景须权衡使用。

8. 使用建议

  • 适用场景

    • 快速查找/去重:不关心顺序,关注高效查找/插入/删除时首选。
    • 元素唯一:需要自动去重功能的集合场景。
  • 不适用场景

    • 有序遍历或范围查询:需保序或区间操作时,改用 std::set 或 std::map。
    • 重复键:若允许多值,使用 std::unordered_multiset。
http://www.xdnf.cn/news/19837.html

相关文章:

  • Java课程内容大纲(附重点与考试方向)
  • 算法01-最小生成树prim算法
  • C语言复习笔记--字符函数和字符串函数(上)
  • Xen安装ubuntu并启动过程记录
  • final关键字带来的问题
  • 大数据赋能,全面提升‘企业服务平台’实际效能!
  • 见多识广3:帕累托最优解与帕累托前沿
  • HAL详解
  • C#学习第16天:聊聊反射
  • API 即 MCP|Higress 发布 MCP Marketplace,加速存量 API 跨入 MCP 时代
  • 电脑开机启动慢的原因
  • Python 的 pip 命令详解,涵盖常用操作和高级用法
  • ES数据库索引报错
  • 十、数据库day02--SQL语句01
  • 基于Python的MCP Server技术解析:从AI代理到实时数据处理的智能化实践
  • 博客系统案例练习-回顾
  • MMAction2安装
  • 3、整合前端基础交互页面
  • 幽灵依赖与常见依赖管理
  • C++每日训练 Day 17:构建响应式加载动画与异步数据处理
  • 笔记本电脑屏幕闪烁是怎么回事 原因及解决方法
  • 【Drools+springboot3规则匹配】
  • 【计算机网络 | 第一篇】计算机网络基础知识
  • 【Linux】部署vfstpd服务端,让客户端通过访问不同的端口号,可以实现访问不同的目录
  • 刀片服务器的散热构造方式
  • C++17 新特性简解
  • 分享4-5月工信部排考计划
  • 评测 Doubao-1.5-thinking-pro | 豆包·深度思考模型
  • “AI问诊助手”落地武汉市中心医院,深兰科技助力医疗数智化升级
  • NOIP2015提高组.信息传递