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

<<哈希表迭代器函数>>

哈希表迭代器是手写哈希表的核心模块,依托KeyOfT取键仿函数实现通用适配,同时打通unordered_map / unordered_set遍历逻辑,是容器实现迭代遍历、范围for循环的底层支撑。哈希表迭代器不同于链表、数组迭代器,需要适配哈希桶数组+单链表的双层结构。

1 迭代器核心原理

哈希表底层结构为:数组(哈希桶)+ 每个桶挂载一条单链表。迭代器的核心工作逻辑:

  • 记录当前遍历的节点指针(当前链表节点)

  • 记录当前遍历的桶下标(定位当前遍历的数组桶)

  • 重载++运算符,实现跨桶、同桶遍历切换

  • 依托KeyOfT适配map/set不同数据类型,实现通用遍历

核心特点:哈希表迭代器是单向迭代器,仅支持前置/后置++,不支持 -- 反向遍历,和STL标准unordered容器迭代器特性一致。

2 迭代器完整源码实现(通用模板)

迭代器封装为模板类,和哈希表、KeyOfT联动,完美适配map、set两种场景,无代码冗余。

// 前置声明哈希表模板类 template<class K, class T, class KeyOfT, class HashFunc> class HashTable; // 哈希表迭代器类 template<class K, class T, class KeyOfT, class HashFunc> struct HashIterator { // 别名定义,简化代码 typedef HashNode<T> Node; typedef HashIterator<K, T, KeyOfT, HashFunc> Self; Node* _pNode; // 当前迭代器指向的节点 size_t _bucketIndex; // 当前所在桶的下标 HashTable<K, T, KeyOfT, HashFunc>* _ht; // 哈希表本体指针 // 构造函数 HashIterator(Node* node, size_t index, HashTable<K, T, KeyOfT, HashFunc>* ht) :_pNode(node) , _bucketIndex(index) , _ht(ht) {} // 重载解引用:返回节点存储的数据 T& operator*() { return _pNode->_data; } // 重载箭头:支持 -> 访问数据成员 T* operator->() { return &_pNode->_data; } // 重载前置++(核心遍历逻辑) Self& operator++() { // 1. 当前桶还有后续节点,直接往后走 if (_pNode->_next != nullptr) { _pNode = _pNode->_next; } // 2. 当前桶遍历完毕,寻找下一个非空桶 else { _bucketIndex++; // 遍历后续所有桶,找到第一个非空桶的头节点 while (_bucketIndex < _ht->_table.size()) { if (_ht->_table[_bucketIndex] != nullptr) { _pNode = _ht->_table[_bucketIndex]; break; } _bucketIndex++; } // 所有桶遍历完毕,迭代器置空(尾后迭代器) if (_bucketIndex >= _ht->_table.size()) { _pNode = nullptr; } } return *this; } // 重载后置++ Self operator++(int) { Self tmp = *this; ++(*this); return tmp; } // 重载相等判断 bool operator!=(const Self& it) { return _pNode != it._pNode; } // 重载不等判断 bool operator==(const Self& it) { return _pNode == it._pNode; } };

3 哈希表配套迭代器接口

在哈希表类中实现begin()end()接口,对外提供遍历入口,适配范围for循环。

// 哈希表类内接口 // 找到第一个非空桶的首节点,返回起始迭代器 iterator begin() { for (size_t i = 0; i < _table.size(); i++) { if (_table[i] != nullptr) { return iterator(_table[i], i, this); } } return end(); } // 尾后迭代器:节点为空 iterator end() { return iterator(nullptr, -1, this); }

4 迭代器与 KeyOfT 的联动关系

迭代器本身不直接处理键值提取,而是通过对外暴露数据,结合KeyOfT实现通用遍历匹配,完美承接前文知识点:

  • 遍历set:迭代器取出T(即K),直接取值使用

  • 遍历map:迭代器取出T(pair<K,V>),通过KeyOfT提取first键,完成查找、比对逻辑

核心逻辑:迭代器负责遍历节点,KeyOfT负责解析数据,二者分工明确,共同实现一套代码适配两种容器。

5 迭代器核心特性

  • 单向遍历:仅支持++,不支持--,属于单向迭代器,契合STL unordered容器特性

  • 跨桶遍历:自动识别当前桶是否遍历完毕,无缝切换下一个非空桶

  • 零开销:模板编译期确定类型,无运行时多态开销

  • 通用性强:依托模板+KeyOfT,同时适配map、set自定义类型遍历

6 迭代器常见易错点

  • 遍历顺序无序:哈希表迭代器遍历顺序并非插入顺序,是哈希桶存储顺序,和STL unordered容器一致

  • 扩容迭代器失效:哈希表扩容后,底层数组重构,原有迭代器全部失效,不可继续使用

  • 不支持反向遍历:未重载--运算符,强行调用会编译报错

  • 尾后迭代器禁止解引用:end()迭代器节点为空,解引用会触发空指针访问崩溃

7 面试高频考点

1、哈希表迭代器为什么不支持反向遍历?

哈希表每个桶是单向链表,仅保存next后继指针,无前驱指针,无法向前遍历;且桶与桶之间无关联,不支持反向迭代。

2、迭代器和KeyOfT的协作逻辑是什么?

迭代器负责遍历所有存储节点,取出原始数据T;KeyOfT负责从T中提取哈希键K,实现遍历过程中的查重、比对、匹配逻辑,是遍历功能通用化的核心。

3、哈希表迭代器失效场景?

主要为扩容场景:插入元素触发扩容后,底层哈希桶数组重新开辟空间,所有节点迁移至新数组,原有迭代器的节点指针、桶下标全部失效。

http://www.jsqmd.com/news/894754/

相关文章:

  • AI开发者的网络卡点:Anthropic连接超时实战避坑指南
  • C51开发中PRECEDE指令导致的内存重叠问题解析
  • Lovable运维平台架构设计深度解析(高可用+低延迟+零信任安全三重验证)
  • Java字符串匹配算法:素数乘积法,秒杀暴力匹配,性能炸裂
  • 从零构建548个免费Web工具:极简架构、自动化与性能优化实战
  • 从‘抽球’到‘预测股价’:离散与连续概率模型在数据分析中的实战对比
  • Iceberg方案:HLS建模范式革新与合成数据增强技术
  • MCP数据库连接器:架构、选型与实战指南
  • 秒杀系统中如何处理超卖问题
  • Unity UGUI ScrollRect 动态折叠菜单避坑指南:ContentSizeFitter 刷新问题的奇葩解法
  • AI代理在生产数据库运维中的五大认知盲区与实战校正
  • 构建AI代理自动化数据管道:从连接器到向量检索的工程实践
  • AI Agent记忆系统:SQLite+FTS5为何比向量数据库更实用?
  • acados MPC求解器实战:8个常见错误排查与解决指南
  • AI代码审查CLI工具十年演进:从功能驱动到体验驱动的开发者体验设计
  • 基于VoIPBin Flows与AI服务构建智能语音交互系统
  • 测绘人效率工具箱:Global Mapper 18.2搭配CASS 11,从数据处理到出图的全链路实战
  • 杰理SDK开发-【BUG】软件开启音量同步连接华为、荣耀手机没有自动开启音量同步
  • MFC窗口防隐藏实战:从WM_SHOWWINDOW到WM_WINDOWPOSCHANGING的踩坑与填坑指南
  • 脉冲神经网络剪枝技术:SPEAR框架的创新与实践
  • 分布式强化学习的网络瓶颈与OLAF优化方案
  • 品达VRF Mini3,极简安装,空调全品牌自适应
  • 从Unity 2022到Unity 6:平台判断API的变迁与未来兼容性写法
  • docker:安装oracle 19c
  • 题⽬ 4:订单商品统计:
  • 构建跨模型智能调度系统:复刻Claude Dispatch体验的技术实践
  • 基于Git与LLM构建代码库知识库:增量维护与智能查询实践
  • 长沙墙外漆
  • 这次走对了,微软AgenticRAG实测5.9倍提升
  • PTPX功耗报告看不懂?别慌,手把手教你拆解Internal/Switch/Leakage Power