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

《C++》哈希表解析与实现

文章目录

    • 一、哈希表基础概念
      • 1.1 什么是哈希表
      • 1.2 为什么需要哈希表
      • 1.3 哈希表的常见应用
    • 二、哈希表核心原理
      • 2.1 哈希函数设计
        • 2.1.1 优秀哈希函数的特性
        • 2.1.2 常见哈希函数
      • 2.2 哈希冲突解决
        • 2.2.1 开放定址法(闭散列)
        • 2.2.2 链地址法 (C++ STL采用此方法)
      • 2.3 装载因子与扩容
    • 三、C++中的哈希表实现
      • 3.1 STL中的unordered_map
      • 3.2 自定义哈希函数
      • 3.3 性能调优
    • 四、手动实现哈希表
      • 4.1 基础哈希表实现
      • 4.2 扩容机制实现
      • 4.3 迭代器实现

一、哈希表基础概念

1.1 什么是哈希表

  • 哈希表(Hash Table)是一种使用哈希函数组织数据的数据结构,它通过把关键码值映射到表中一个位置来访问记录,以实现快速查找。简单来说,哈希表就是一个"键-值"对的集合,能够根据键快速找到对应的值。

  • 哈希表的核心思想是:用空间换时间。它通过预先分配一个较大的数组,然后使用哈希函数将键转换为数组下标,从而实现平均时间复杂度为O(1)的查找、插入和删除操作。

1.2 为什么需要哈希表

在没有哈希表的情况下,我们通常使用数组或链表来存储数据:

  • 数组:查找快(O(1)),但插入和删除慢(O(n))
  • 链表:插入和删除快(O(1)),但查找慢(O(n))

哈希表结合了两者的优点,在大多数情况下都能提供O(1)时间复杂度的操作,极大地提高了数据处理的效率。

1.3 哈希表的常见应用

哈希表在编程中无处不在,典型应用包括:

  1. 字典实现:C++中的unordered_map
  2. 网页去重:检测重复URL
  3. 拼写检查:快速查找单词是否正确

二、哈希表核心原理

2.1 哈希函数设计

2.1.1 优秀哈希函数的特性
  • 确定性:相同输入总是产生相同输出

  • 均匀性:哈希值应均匀分布

  • 高效性:计算速度快

  • 抗碰撞性:不同输入产生相同输出的概率低

2.1.2 常见哈希函数
  • ​​直接定址法​​:Hash(key) = a*key + b

  • 除留余数法​​:Hash(key) = key % p(p最好是质数)

  • ​​平方取中法​​:取key平方的中间几位

  • ​​折叠法​​:将key分成几部分后相加

  • ​​随机数法​​:Hash(key) = random(key)

2.2 哈希冲突解决

2.2.1 开放定址法(闭散列)
  • 线性探测​​:依次检查下一个位置

  • ​​二次探测​​:使用二次方程计算探测位置

  • 双重哈希​​:使用第二个哈希函数

2.2.2 链地址法 (C++ STL采用此方法)
  • 每个桶位置维护一个链表

  • 冲突元素追加到链表末尾

2.3 装载因子与扩容

装载因子(Load Factor)是哈希表中已存储元素数量与哈希表大小的比值。当装载因子超过某个值(通常为0.7-0.8)时,哈希表的性能会显著下降,此时需要进行扩容。扩容的操作包括以下步骤:

  1. 创建一个更大的哈希表(通常是原大小的2倍)
  2. 重新计算所有元素的哈希值并插入新表
  3. 释放原表的空间

三、C++中的哈希表实现

3.1 STL中的unordered_map

C++11引入了unordered_map,它是基于哈希表实现的关联容器,使用非常方便:

#include <unordered_map>
#include <string>std::unordered_map<std::string, int> wordCount;// 插入元素
wordCount["apple"] = 5;
wordCount.insert({"banana", 3});// 访问元素
std::cout << "apple count: " << wordCount["apple"] << std::endl;// 遍历
for (const auto& pair : wordCount) {std::cout << pair.first << ": " << pair.second << std::endl;
}

3.2 自定义哈希函数

当使用自定义类型作为键时,需要提供哈希函数和相等比较函数:

struct Person {std::string name;int age;
};// 自定义哈希函数
struct PersonHash {size_t operator()(const Person& p) const {return std::hash<std::string>()(p.name) ^ std::hash<int>()(p.age);}
};// 自定义相等比较
struct PersonEqual {bool operator()(const Person& p1, const Person& p2) const {return p1.name == p2.name && p1.age == p2.age;}
};std::unordered_map<Person, std::string, PersonHash, PersonEqual> personMap;

3.3 性能调优

unordered_map提供了一些调整性能的参数:

  • bucket_count:桶的数量
  • load_factor:当前装载因子
  • max_load_factor:最大允许装载因子
std::unordered_map<std::string, int> myMap;// 预留空间,避免频繁扩容
myMap.reserve(1000);// 设置最大装载因子
myMap.max_load_factor(0.75);// 获取桶数量
std::cout << "Bucket count: " << myMap.bucket_count() << std::endl;

四、手动实现哈希表

4.1 基础哈希表实现

#include <vector>
#include <list>template <typename K, typename V>
class HashTable {
private:struct KeyValue {K key;V value;KeyValue(const K& k, const V& v) : key(k), value(v) {}};std::vector<std::list<KeyValue>> table;size_t size;size_t hash(const K& key) const {return std::hash<K>()(key) % table.size();}public:HashTable(size_t initialSize = 101) : table(initialSize), size(0) {}void insert(const K& key, const V& value) {size_t index = hash(key);for (auto& kv : table[index]) {if (kv.key == key) {kv.value = value;return;}}table[index].emplace_back(key, value);size++;}bool find(const K& key, V& value) const {size_t index = hash(key);for (const auto& kv : table[index]) {if (kv.key == key) {value = kv.value;return true;}}return false;}void remove(const K& key) {size_t index = hash(key);for (auto it = table[index].begin(); it != table[index].end(); ++it) {if (it->key == key) {table[index].erase(it);size--;return;}}}
};

4.2 扩容机制实现

添加自动扩容功能,当装载因子过高时自动扩展哈希表:

void checkLoadFactor() {double loadFactor = static_cast<double>(size) / table.size();if (loadFactor > 0.7) {rehash(table.size() * 2);}
}void rehash(size_t newSize) {std::vector<std::list<KeyValue>> newTable(newSize);for (auto& bucket : table) {for (auto& kv : bucket) {size_t newIndex = std::hash<K>()(kv.key) % newSize;newTable[newIndex].push_back(kv);}}table = std::move(newTable);
}

4.3 迭代器实现

为哈希表添加迭代器支持,使其更符合STL风格:

class iterator {typename std::vector<std::list<KeyValue>>::iterator vecIt;typename std::list<KeyValue>::iterator listIt;std::vector<std::list<KeyValue>>* table;public:iterator(std::vector<std::list<KeyValue>>* t, typename std::vector<std::list<KeyValue>>::iterator vi,typename std::list<KeyValue>::iterator li): table(t), vecIt(vi), listIt(li) {}KeyValue& operator*() { return *listIt; }KeyValue* operator->() { return &(*listIt); }iterator& operator++() {++listIt;if (listIt == vecIt->end()) {++vecIt;while (vecIt != table->end() && vecIt->empty()) {++vecIt;}if (vecIt != table->end()) {listIt = vecIt->begin();}}return *this;}bool operator!=(const iterator& other) const {return vecIt != other.vecIt || listIt != other.listIt;}
};iterator begin() {auto vecIt = table.begin();while (vecIt != table.end() && vecIt->empty()) {++vecIt;}if (vecIt != table.end()) {return iterator(&table, vecIt, vecIt->begin());}return end();
}iterator end() {return iterator(&table, table.end(), typename std::list<KeyValue>::iterator());
}
http://www.dtcms.com/a/331216.html

相关文章:

  • 能源行业数字化转型:边缘计算网关在油田场景的深度应用
  • Python机器学习与深度学习;Transformer模型/注意力机制/目标检测/语义分割/图神经网络/强化学习/生成式模型/自监督学习/物理信息神经网络等
  • 基于51单片机倒计时器秒表定时器数码管显示设计
  • vue+后端
  • 微服务、分布式概念-以及集群部署 vs 分布式部署
  • 容器运行时支持GPU,并使用1panel安装ollama
  • 将 pdf 转为高清 jpg
  • 数巅中标中建科技AI知识库项目,开启建筑业数智化新篇章
  • CSS aspect-ratio 属性
  • Multimodal RAG Enhanced Visual Description
  • Linux 对 RPM 包的管理
  • 19 ABP Framework 本地化系统
  • hashmap和concurrentHashmap是否允许null值和null健
  • PiscCode使用光流法计算漂浮物位移速度
  • 把 AI 推理塞进「 8 位 MCU 」——0.5 KB RAM 跑通关键词唤醒的魔幻之旅
  • 监控插件SkyWalking(一)原理
  • 嵌入式学习的第四十九天-时钟+EPIT+GPT定时器
  • 无人机探测器技术解析
  • 阿里巴巴 Qwen-Image:免费开源,还要挑战 GPT-4.1 和 Midjourney?
  • 恢复GPT-4o,增加付费配额:OpenAI的“补救措施”如何重塑用户金字塔
  • OpenCV ------图像基础处理(一)
  • 【OpenCV】Mat详解
  • 论,物联网日志系统架构如何设计?
  • AI增强SEO关键词表现
  • Postman 平替 技术解析:架构优势与实战指南
  • 审批流程系统设计与实现:状态驱动、灵活扩展的企业级解决方案
  • Java研学-RabbitMQ(八)
  • Rabbitmq+STS+discovery_k8s +localpv部署排坑详解
  • 队列的使用以及泛型思考[二叉树的层序遍历]
  • 【P27 4-8】OpenCV Python——Mat类、深拷贝(clone、copyTo、copy)、浅拷贝,原理讲解与示例代码