跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ Unordered 系列容器及哈希表底层原理实现

综述由AI生成C++11 引入 unordered 系列容器,底层基于哈希表实现 O(1) 查询效率。模拟实现了 HashBucket、UnorderedMap 和 UnorderedSet,详细讲解了哈希冲突解决(开散列/链地址法)、节点设计、扩容机制及迭代器实现。通过模板特化支持 string 作为 Key,并封装了 Map 的 [] 运算符重载逻辑。

PentesterX发布于 2026/3/24更新于 2026/5/2316K 浏览
C++ Unordered 系列容器及哈希表底层原理实现

Unordered 系列容器概述

在 C++98 中,STL 提供了底层为红黑树的关联式容器(map/set),查询效率为 O(logN)。为了追求极致的查找速度,C++11 引入了 unordered 系列容器,其底层采用哈希表结构,理论上查询效率可达到 O(1)。

本文将模拟实现代码(HashBucket, UnorderedMap, UnorderedSet),深入剖析其底层原理与实现细节。


1. 哈希基础与冲突解决

1.1 哈希概念

哈希(Hash)通过一个哈希函数(HashFunc),将元素的关键码(Key)映射到存储位置,建立一一映射关系,从而实现不经过比较直接查找元素。

公式:hash(key) = key % capacity

1.2 哈希冲突

当不同的关键字通过哈希函数计算出相同的哈希地址时,就会发生哈希冲突(Hash Collision)。解决冲突主要有两种方式:

A. 闭散列(开放定址法)

当发生冲突时,如果哈希表未满,将 key 存放到冲突位置的'下一个'空位置。

线性探测:挨个往后找。容易产生'数据堆积'。
二次探测:通过跳转查找,缓解堆积。

B. 开散列(链地址法/哈希桶)

这是 STL unordered_map 通常采用的方法,也是我们代码中实现的方法。

原理:将具有相同哈希地址的元素归于同一子集合(桶),每个桶通过单链表链接。哈希表中存储的是链表的头指针。


2. 模拟实现:底层哈希桶 (HashBucket)

我们在 HashBucket.h 中实现了开散列的哈希表。

2.1 节点设计

使用模板结构体 HashNode,存储数据和下一个节点的指针。

template <class T>
struct HashNode {
    T _data;
    HashNode* _next;
    // ... 构造函数
};

2.2 哈希函数与字符串特化

为了支持 string 作为 Key,我们需要对哈希函数进行特化。代码中使用了类似 BKDRHash 的思路(乘数为 31)将字符串转化为整型。

template <>
struct HashFunc<string> {
    const int operator()(const string& str) {
        int hashi = ;
         ( i = ; i < str.(); i++) {
            hashi += str[i];
            hashi *= ; 
        }
         hashi;
    }
};
0
for
int
0
size
31
// 经典乘数,减少冲突
return

2.3 插入与扩容

插入 (Insert):

  1. 先查找元素是否存在,存在则返回 false。
  2. 扩容检查:在开散列中,当元素个数 == 桶的个数(负载因子为 1)时,冲突概率变大,需要扩容。
  3. 头插法:计算下标 index,将新节点插入到 _table[index] 的头部(效率最高)。

复用节点:
在扩容时,代码没有创建新节点,而是直接将旧表的节点'搬运'到新表,节省了 new 和 delete 的开销。

if (_n == _table.size()) {
    vector<Node*> newHt;
    newHt.resize(_n * 2);
    // 遍历旧表,重新计算 hash 值挂到新表
    // ...
    _table.swap(newHt);
}

2.4 迭代器设计

unordered 容器的迭代器是单向迭代器(Forward Iterator)。

  • 结构:迭代器需要持有 Node*(当前节点)和 HashBucket*(哈希表指针)。

  • operator++ 实现逻辑:

    1. 如果当前桶的链表还没走完 (_node->_next != nullptr),则指向下一个节点。
    2. 如果当前桶走完了,利用 _ht 指针计算当前桶的下标,并在哈希表中向后寻找第一个非空的桶。

3. 封装:UnorderedSet 与 UnorderedMap

为了复用同一份 HashBucket 代码,我们利用模板参数采用了类似适配器模式的设计。

3.1 提取 Key 的策略 (KeyOfT)

HashBucket 存储的是 T,但不知道 T 中哪个部分是 Key。

  • UnorderedSet:存储的是 Key,T 就是 K。SetOfT 仿函数直接返回 Key。
  • UnorderedMap:存储的是 pair<K, V>。MapOfT 仿函数返回 pair.first。

3.2 UnorderedMap 的 operator[]

map 的 [] 运算符非常强大:如果 Key 存在则查找,不存在则插入默认值。
实现逻辑是调用 Insert,利用其返回值 pair<iterator, bool> 来获取 Value 的引用。

V& operator[](const K& key) {
    auto it = Insert(make_pair(key, V())).first;
    return (*it).second;
}

总结

以上就是对哈希相关内容的总结了。

目录

  1. Unordered 系列容器概述
  2. 1. 哈希基础与冲突解决
  3. 1.1 哈希概念
  4. 1.2 哈希冲突
  5. A. 闭散列(开放定址法)
  6. B. 开散列(链地址法/哈希桶)
  7. 2. 模拟实现:底层哈希桶 (HashBucket)
  8. 2.1 节点设计
  9. 2.2 哈希函数与字符串特化
  10. 2.3 插入与扩容
  11. 2.4 迭代器设计
  12. 3. 封装:UnorderedSet 与 UnorderedMap
  13. 3.1 提取 Key 的策略 (KeyOfT)
  14. 3.2 UnorderedMap 的 operator[]
  15. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Llama Factory 无代码微调大模型指南
  • IntelliJ IDEA 集成使用 Claude Code 方法指南
  • 国内直连 AI 绘画工具深度实践与部署指南
  • C++ 多态原理详解:虚函数表与动态绑定
  • 异构数据迁移工具:DataX 与 DataX-Web 部署指南
  • PyWebView 跨平台桌面应用开发指南
  • Midjourney 官网地址及中文支持情况说明
  • 632. 最小区间 - 贪心算法思路与实现
  • AIOps 实践:使用 Dify+LangBot 搭建飞书智能体机器人
  • 基于 Vulkan 的游戏引擎平面反射实现方案
  • SQL Server Management Studio (SSMS) 安装教程
  • Python 行为树编程实战技巧:构建智能决策系统
  • 基于 Java Socket 实现多人在线聊天系统
  • 前端地图开发基础:服务类型、坐标系与 SDK 简介
  • Java 主流开发框架及项目选型指南
  • Java 入门基础:JDK 配置、IDEA 安装与 Hello World 实战
  • F5 刷新后,浏览器前端究竟发生了什么?
  • 前端防录屏原理:EME 与 DRM 技术解析及实战
  • CentOS 系统定时执行 Python 邮件发送任务的五种方案
  • 通过 Logit Bias 精细调控大模型词汇生成

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online