C++简单实现哈希查找

C++ 简单实现哈希查找

1. 哈希冲突

哈希表中可能会出现哈希冲突,即多个数据项映射到相同的桶。

常见的冲突解决方法包括链地址法(Chaining)和线性探测法(Linear Probing)。

  • 使用链地址法时,每个桶维护一个链表,哈希冲突的数据项被插入到链表中。查找时,遍历链表以查找目标数据项。
  • 使用线性探测法时,如果一个桶已经被占用,算法会线性地探测下一个可用的桶,直到找到目标数据项或空桶。这种方法需要特别处理删除操作。

2. 算法执行过程

  • 初始化哈希表:创建一个固定大小的数组,将每个元素的值设置为其索引。
  • 插入元素:根据要插入的元素计算其哈希值,然后将该元素插入到对应索引的位置。如果发生哈希冲突(即两个不同的元素具有相同的哈希值),则在相应索引位置存储一个链表,链表中存储具有相同哈希值的所有元素。
  • 查找元素:首先计算要查找元素的哈希值,然后根据哈希值找到对应的索引位置。如果该位置没有其他元素,说明找到了目标元素;否则,在对应索引位置的链表中继续查找。
  • 删除元素:如果要删除的元素恰好等于目标元素,那么直接删除即可;否则,需要找到该元素所在的链表,并从链表中删除该元素。
  • 扩容:当哈希表的大小超过了数组的最大容量时,需要对数组进行扩容,即创建一个新的更大的数组,并将原数组中的元素重新插入到新数组中。同时,还需要重新计算所有元素的哈希值,并将它们插入到新数组的相应位置。****

3. 例题

例题:

有序表 A[20] = {4,6,12,20,28,38,50,70,88,100},使用哈希查找算法找出元素 20

4. 步骤

为了使用哈希查找方法实现有序表A[20]:

  • 我们需要首先定义哈希表的大小。哈希表的大小通常比表中元素的最大值要大,以确保所有元素都能被存储,并且有足够的空间来解决哈希冲突。
  • 接下来,我们需要定义一个哈希函数。一个简单的哈希函数可以是将元素值除以哈希表大小,然后取整数部分。
  • 在这个例子中,我们的哈希表大小为10,所以哈希函数可以是 h(x) = x % 10。对于整数,这个函数将把每个元素映射到一个在0到9之间的位置。
  • 现在,我们可以开始将元素插入哈希表中。由于我们使用线性探索来解决冲突,当冲突发生时,我们将在哈希表中的当前位置开始线性搜索,直到找到一个空位置为止。

以下是插入过程的步骤:

  1. 初始化哈希表:hashTable[10] = {NULL},其中 NULL 表示空位置。
  2. 对于表A中的每个元素x:
    • 计算哈希值:h(x) = x % 10
    • 确定哈希位置:index = h(x)
    • 如果 hashTable[index]NULL,则将x插入到 hashTable[pos]
    • 如果 hashTable[index]不为 NULL,则进行线性探索,寻找空位置。线性探索可以从 index + 1 开始,直到找到空位置。
  3. 重复步骤2,直到表A中的所有元素都被插入到哈希表中。
    下面是具体的插入过程:
  • 对于4,h(4) = 4 % 10 = 4, hashTable[4] 为空,插入。
  • 对于20,h(20) = 12 % 10 = 0hashTable[0] 为空,插入。
  • 对于50,h(50) = 50 % 10 = 0,但 hashTable[0] 已被占用,进行线性探索,hashTable[1] 为空,插入。
  • 依此类推,直到所有元素都被插入到哈希表中。

最终的哈希表 hashTable 将包含有序表 A 的元素,可能有一些位置为 NULL,表示在插入过程中没有发生冲突。

为了查找表中的一个元素x,我们同样使用哈希函数计算其哈希值,然后在哈希表中定位该值。

如果在定位的位置找到了元素 x,则查找成功;如果找到了 NULL,则说明元素 x 不在表中。

需要注意的是,线性探索虽然简单,但在高负载情况下(即哈希表的装载因子较高)会导致性能下降,因为可能会出现较长的查找链。

在实际应用中,可能会采用更复杂的哈希函数和冲突解决策略来提高效率。

5. 代码

#include <iostream>
#include <vector>using namespace std;// 哈希表的大小
const int HASH_TABLE_SIZE = 10;
// 哈希表
vector<int> hashTable(HASH_TABLE_SIZE, 0);  // 初始化为NULL
// 哈希函数
int hashFunction(int key) {return key % HASH_TABLE_SIZE;
}
// 线性探查
int linearProbing(int key) {int index = hashFunction(key);while (hashTable[index] != 0 && hashTable[index] != key) {index = (index + 1) % HASH_TABLE_SIZE;  // 线性探查}return index;
}// 插入键值对
void insert(int key) {int index = linearProbing(key);if (hashTable[index] == 0) {hashTable[index] = key;} else {cout << "冲突发生,键 " << key << " 已存在。" << endl;}
}// 查找键
int search(int key) {int index = hashFunction(key);while (hashTable[index] != 0) {if (hashTable[index] == key) {return index;}index = (index + 1) % HASH_TABLE_SIZE;  // 线性探查}return -1;  // 未找到键
}int main() {// 初始化有序表int A[10] = {4, 6, 12, 20, 28, 38, 50, 70, 88, 100};// 插入元素for (int i = 0; i < 10; ++i) {insert(A[i]);}for (int i = 0; i < 10; ++i) {cout << hashTable[i] << " ";}cout << endl;// 搜索元素int keyToSearch = 20;int index = search(keyToSearch);if (index != -1) {cout << "键 " << keyToSearch << " 在哈希表中的位置是: " << index << endl;} else {cout << "键 " << keyToSearch << " 在哈希表中未找到。" << endl;}return 0;
}

6. 使用场景

  1. 字典和关联数组:哈希表常用于实现字典和关联数组,其中键映射到值。这样可以快速查找特定键对应的值。
  2. 缓存:哈希表用于数据缓存,允许快速访问已经检索的数据,以减少对慢速存储介质(如磁盘)的访问。
  3. 数据库索引:在数据库管理系统中,哈希表用于构建索引,以便快速检索和访问数据库中的数据。这在大型数据库中非常有用。
  4. 散列集合:编程语言中的集合(Set)和散列集合(HashSet)通常使用哈希表来实现,以便快速查找成员。
  5. 数据去重:哈希表可用于检测和删除重复数据项。通过将数据插入哈希表并检查是否已经存在,可以有效去重。
  6. 认证和授权:哈希表可用于存储用户凭据(如用户名和密码)或授权令牌,以便快速验证用户身份。
  7. 编译器符号表:编程语言编译器使用哈希表来管理符号表,以便快速查找变量、函数和其他符号的定义和引用。
  8. 数据分布:在分布式计算中,哈希表用于确定数据项应该存储在哪个节点或分片,以实现均匀的数据分布。
  9. 缓存管理:缓存管理系统通常使用哈希表来跟踪缓存的内容,以加速数据检索。
  10. 路由表:网络路由器使用哈希表来管理路由表,以确定数据包的转发路径。
  11. 文件系统索引:文件系统通常使用哈希表来维护文件索引,以加速文件查找和访问。
  12. 编码查找表:在编码和解码中,哈希表可用于存储查找表,以实现快速的字符或编码查找。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/765886.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle里表、索引、列的统计信息

目录 一、表的统计信息 二、索引的统计信息 1、层级&#xff08;level&#xff09; 2、聚簇因子的含义及重要性 3、列的统计信息 3.1直方图&#xff08;histogram&#xff09; 1&#xff09;直方图含义 2&#xff09;直方图类型 一、表的统计信息 表的统计信息用于描述表…

【保姆级教程】YOLOv8目标检测:训练自己的数据集

一、YOLOV8环境准备 1.1 下载安装最新的YOLOv8代码 仓库地址&#xff1a; https://github.com/ultralytics/ultralytics1.2 配置环境 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple二、数据准备 2.1 安装labelme标注软件 pip install label…

React系列 之 React进阶 含源码解读 (一)事件合成、state原理

资料来源&#xff1a;掘金课程 https://juejin.cn/book/6945998773818490884?enter_fromcourse_center&utm_sourcecourse_center 记录一些笔记 事件合成 React的事件其实是React重新实现的一套事件系统。目标是统一管理事件&#xff0c;提供一种跨浏览器一致性的事件处…

langchain4j DefaultAiServices源码解析

版本 0.28.0 源码 使用langchain4j&#xff0c;可以通过AiServices来封装聊天模型API&#xff0c;实现会话记忆&#xff0c;工具调用&#xff0c;搜索增强&#xff0c;内容审查等功能&#xff0c;并提供简单灵活的用户接口 DefaultAiServices是其默认实现类型&#xff0c;通…

5G智能网关助力工业铸造设备监测升级

随着物联网技术的迅猛发展和工业4.0浪潮的推进&#xff0c;传统工业正面临着严峻的转型升级压力。在这一背景下&#xff0c;铸造行业——这一典型的传统重工业领域&#xff0c;也必须积极探索借助5G、物联网、边缘计算等技术提升生产经营效率的新路径。 本文就基于佰马合作伙伴…

【技巧】ChatGPT Prompt 提示语大全

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 主要来自&#xff1a;https://github.com/f/awesome-chatgpt-prompts ChatGPT SEO提示 Contributed by: StoryChief AI Reference: 7 Powerful ChatGPT Prompts to Create SEO Content Faster 供稿人&#xff1a;…

MyBatis Plus笔记

1、删除 物理删除&#xff1a;从硬盘上直接删除掉 。好处&#xff1a;数据条数少了&#xff0c;不好的地方在于可能会影响到基于这条数据产生的记录 逻辑删除&#xff1a;假删除 两个区别&#xff1a; 删除时 之前&#xff1a;DELETE from sys_user …

链表oj测试题(上)

链表的申明&#xff1a; struct ListNode {int val;struct ListNode* next; }; 1.题1 删除指定元素 例如&#xff1a;链表1 2 6 3 4 5 6&#xff0c;然后选择删除元素6&#xff0c;返回的链表为1 2 3 4 5 。 代码演示&#xff1a; typedef struct ListNode ListNode;List…

Spark与flink计算引擎工作原理

Spark是大批量分布式计算引擎框架&#xff0c;scale语言开发的&#xff0c;核心技术是弹性分布式数据集&#xff08;RDD&#xff09;可以快速在内存中对数据集进行多次迭代&#xff0c;支持复杂的数据挖掘算法及图形计算算法&#xff0c;spark与Hadoop区别主要是spark多个作业之…

什么是行业垂直类媒体?有哪些?怎么邀约

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体胡老师。 行业垂直类媒体是聚焦于特定行业或领域的媒体平台。 行业垂直类媒体不同于主流媒体&#xff0c;它们专注于提供与某个特定领域相关的深入内容和服务&#xff0c;例如商业新闻、旅游、数字…

能拍英语的搜题软件?九个免费好用的大学生搜题工具 #经验分享#知识分享#其他

积极参加社团活动和实践项目&#xff0c;可以帮助大学生拓宽人脉圈和锻炼实际操作能力。 1.粉鹿搜题 这是一个公众号 搜题拥有非常强大的题库&#xff0c;包含IT认证、建筑工程:、会计资格、教师资格、研究生、公务员等类型的题目。 下方附上一些测试的试题及答案 1、BPR基…

面试算法-79-搜索旋转排序数组

题目 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nums[1…

Qt 利用共享内存实现一次只能启动一个程序(单实例运行)

Qt 利用共享内存实现一次只能启动一个程序 文章目录 Qt 利用共享内存实现一次只能启动一个程序摘要利用共享内存实现一次只能启动一个程序示例代码 关键字&#xff1a; Qt、 unique、 单一、 QSharedMemory、 共享内存 摘要 今天接着在公司搞我的屎山代码&#xff0c;按照…

[MAUI]集成高德地图组件至.NET MAUI Blazor项目

文章目录 前期准备&#xff1a;注册高德开发者并创建 key登录控制台创建 key获取 key 和密钥 创建项目创建JS API Loader配置权限创建定义创建模型创建地图组件创建交互逻辑 项目地址 地图组件在手机App中常用地理相关业务&#xff0c;如查看线下门店&#xff0c;设置导航&…

LeetCode 热题 100 | 堆(二)

目录 1 什么是优先队列 1.1 优先队列与堆的关系 1.2 如何定义优先队列 1.3 如何使用优先队列 1.4 如何设置排序规则 2 347. 前 K 个高频元素 2.1 第 2 步的具体实现 2.2 举例说明 2.3 完整代码 3 215. 数组中的第 K 个最大元素 - v2 菜鸟做题&#xff0c;语…

Shell学习

一、 变量 shell是弱类型语言&#xff0c;不用定义数据类型&#xff0c;默认都是字符串。 变量与值之间不得有空格 只能包含数字、字母、下划线 不能以数字开头 区分大小写 根据变量的作用域可以将shell变量分为&#xff1a;全局变量、局部变量、环境变量。全局变量通常和…

app自动化测试怎么学?

app测试的主要内容有那些 1、功能测试 : 查看功能是否正常&#xff0c;主要针对每一个功能点进行一一测试&#xff0c;主要核心就是把验证的每个测试点都满足需求的对应功能&#xff0c;验证标准就是让预期结果和实际结果保持一致。 2、安装卸载测试&#xff1a;首先要测试的…

【Linux】从零认识进程 — 中下篇

送给大家一句话&#xff1a; 人一切的痛苦&#xff0c;本质上都是对自己无能的愤怒。而自律&#xff0c;恰恰是解决人生痛苦的根本途径。—— 王小波 从零认识进程 1 进程优先级1.1 什么是优先级1.2 为什么要有优先级1.3 Linux优先级的特点 && 查看方式1.4 其他概念 2…

深度解析深度学习中的长短期记忆网络(LSTM)(含代码实现)

在深度学习中&#xff0c;长短期记忆网络&#xff08;LSTM&#xff09;是一种强大的循环神经网络结构&#xff0c;能够更好地处理长序列数据并减轻梯度消失的问题。本文将介绍LSTM的工作原理&#xff0c;并使用PyTorch实现一个简单的LSTM模型来展示其在自然语言处理中的应用。 …

MongoDB完全开发手册(一篇学会MongoDB所有知识点)

目录 一、MongoDB 基础 1.1 、MongoDB 是什么&#xff1f; 1.2、 MongoDB 的存储结构是什么&#xff1f; 1.3 、文档 1.4 、集合 1.5 、数据库 1.6、 MongoDB 有什么特点&#xff1f; 1.7、 MongoDB 适合什么应用场景&#xff1f; 二、MongoDB 存储引擎 2.1 、MongoDB…