哈希表1中我们简单的认识了一下哈希表的相关内容本章让我们一起完成哈希表的构建和相关操作的代码实现吧代码0.结构体的定义hash表和hash桶节点//hash表的默认负载因子 #define LOAD_FACTOR (0.7) typedef int KeyType;//key类型 typedef const char* ValType;//val类型 typedef size_t (*HashFuncType)(KeyType);//定义函数指针类型 //桶节点结构 typedef struct _HashNode{ KeyType key; ValType val; struct _HashNode* next;//实现链表结构 }HashNode; //hash表结构 typedef struct _HashTable { HashNode** bucket;//中控hash桶 int capacity;//桶的容量 int size;//当前数据量 HashFuncType hash_func;//hash函数 }HashTable;1.初始化//实现一个默认的hash函数 static size_t DefaultHashFunc(KeyType key) { return key; }bool HashTableInit(HashTable* table,int bucket_count, HashFuncType hf) { //指针参数校验 assert(table!NULL); //初始化桶申请空间并把指向的地址全部赋值为NULL table-bucket(HashNode**)malloc(sizeof(HashNode*)*bucket_count); if(table-bucketNULL) { printf(malloc申请空间失败); return false; } for(int i0;ibucket_count,i) { table-bucket[i]NULL; } //初始化其它成员 table-capacitybucket_count; table-size0; if(hfNULL)//如果hf传入的是NULL { table-hash_funcDefaultHashFunc;//就使用默认的hash函数 } return true; }2.判空bool HashTableIsEmpty(const HashTable* table) { assert(table!NULL); return table-sizeNULL; }3.插入数据//计算最终存放桶的位置 static size_t HashPos(size_t hash_val,int capacity) { //使用hash值对容量进行取模 return hash_val % capacity; }//新建桶节点函数 static HashNode* NewHashNode(KeyType key, ValType val) { //申请空间初始化成员 HashNode* node (HashNode*)malloc(sizeof(HashNode)); if (node NULL) { LOG(申请新节点空间失败); return NULL; } node-key key; node-val val; node-next NULL; return node; }//检测负载率是否达到负载因子 //达到了说明目前该hash表的冲突概率极高需要进行扩容 bool CheckFactor(HashTable* table) { assert(table!NULL); double x(double)table-size/(double)table-capacity; //如果未达到直接返回 if(xLOAD_FACTOR) { printf(未达负载因子无需扩容) return true; } //达到了扩容 //这里不能使用realloc因为key算出的位置会因为容量的扩大而改变 //1.申请二倍原空间大小的空间 int newcapacity2*table-capacity; HashNode** new_bucket(HashNode**)malloc(sizeof(HashNode*)*newcapacity); if(new_bucketNULL) { printf(malloc申请扩容空间失败); return false; } //2.全部赋值为NULL for(int i0;inewcapacity;i) { new_bucket[i]NULL; } //3.计算原桶节点的新位置并放入新桶中 for(int i0;itable-capacity;i) { while(table-bucket[i]!NULL) { HashNode* curtable-bucket[i]; table-bucket[i]cur-next; //计算新位置 int posHashPos(table-hash_func(cur-key,cur-val),newcapacity); //头插 cur-nextnew_bucket[pos]; new_bucket[pos]cur; } } 4.释放原桶使用新桶 free(table-bucket); table-bucketnew_bucket; table-capacitynewcapacity; return true; }bool HashTableInsert(HashTable* table, KeyType key, ValType val) { //参数校验 assert(table!NULL); //计算要存放的桶的位置 int posHashPos(table-hash_func(key),table-capacity); //遍历判断该桶中是否存在相同的key的节点 HashNode* curtable-bucket[pos]; while(cur!NULL) { //如果存在修改val直接返回true if(cur-keykey) { cur-valval; return true; } } //如果不存在新建桶节点,头插进该链表 CheckFactor(table);//检测是否达到负载因子 HashNode* pNewHashNode(key,val); p-nexttable-bucket[pos]; table-bucket[pos]p; //数据量加一 table-size; return true; }4.查找数据并保存valbool HashTableFind(const HashTable* table, KeyType key, ValType *val) { //参数校验 assert(table!NULLVAL!NULL); //计算查找位置 int posHashPos(table-hash_fuc(),table-capacity); //查找有无相同的key的节点 HashNode* curtable-bucket[pos]; while(cur!NULL) { //找到了保存值并返回true if(cur-keykey) { *valcur-val; return true; } curcur-next; } //未找到 return false; }5.删除数据bool HashTableRemove(HashTable* table, KeyType key) { //参数校验 assert(table!NULL); //计算位置并查找有无key的节点 int posHashPos(table-hash_func(key),table-capacity); HashNode* curtable-bucket[pos] HashNode* prevNULL;//保存前驱节点 while(cur!NULL) { //存在 if(cur-keykey) { if(prevNULL)//cur为首元节点 { table-bucket[pos]cur-next; }else { prev-nextcur-next; } free(cur); curNULL; table-size--; return true; } prevcur; curcur-next; } //不存在 printf(数据不存在); return true; }6.获取元素个数int HashTableSize(const HashTable* table) { assert(table!NULL); return table-size; }7.销毁HashTableDestroy(HashTable* table) { assert(table!NULL); //1.释放桶中所有节点 if (table-bucket ! NULL) //不能重复释放 { for (int i 0; i table-capacity; i) { while (table-bucket[i]!NULL) { HashNode* node table-bucket[i]; table-bucket[i] node-next; free(node); } } } //2.释放桶初始化所有属性 free(table-bucket); table-bucket NULL; table-capacitytable-size0; table-hash_fucNULL; return true; }_____________________________________________________________________________哈希表的相关操作的实现就完成了这只是一个简易的哈希表仅供参考学习感谢您的观看
企业数字化 ERP 产品动态
相关推荐
css盒子模型讲解 一、盒子模型解决什么问题控制盒子内容大小、内边距、边框、外边距区分:元素本身占多大空间、它和别的盒子之间留多大空隙解决尺寸计算混乱的痛点(标准盒 / IE 怪异盒两种计算规则)实现元素之间拉开距离、加边框、背景留白、模块排版盒子四层… · 2026/11/8 22:26:02
【机器视觉】必会算法之:CLIP(对比语言-图像预训练) 机器视觉之:CLIP1、引言2、CLIP(Contrastive Language-Image Pre-training)2.1 定义与解析2.2 核心原理2.2.1 双塔结构:图像编码器 文本编码器2.2.2 对比学习:把"配对"拉近、把"非配对"推远2.2.3 训练数据:4… · 2026/11/5 15:40:12
如何看待DeepSeek和OpenAI都开源了各自的harness? 我觉得,这两家的 Harness 开源说明,大模型公司越来越重视模型之外的执行系统。尤其是 OpenAI。它经常被吐槽不够 Open,却愿意开放 Codex 背后的执行系统。要理解这个选择,得先看看我们使用 AI 的方式发生了什么变化。01从 Chatbot… · 2026/11/5 1:17:43
安全生产事故电工证报名费多少钱 电工证难考?郑州报考避坑指南教你一步到位拿证上岗 急需特种作业证才能上岗找工作,这话说得一点都不夸张。尤其是在郑州这样的大城市,没有安全生产事故电工证,连面试资格都可能被刷掉。不管是刚毕业的大学生,还是想转行的打工族,特种作业证都成了就业门… · 2026/11/10 23:54:47
漳州电工证在哪里学怎么考才不会白交钱?网上查询有妙招 漳州电工证在哪里学怎么考才不会白交钱?网上查询有妙招 怕考不过白交培训费?别慌,漳州电工证在哪里学,不是随便找个培训机构就能搞定的事,很多人花了几千块报班,最后还是考不过,白费钱又浪费时间。其实,只要掌握对方法, 网上查询… · 2026/11/10 23:54:47
全南电工证办理条件多久拿证?别被中介坑了,教你一次搞懂 全南电工证办理条件多久拿证?别被中介坑了,教你一次搞懂 不知道去哪报名怕被中介坑?全南电工证办理条件你真的了解吗?多久拿证?别急,这篇文章给你讲透,从报名到取证,一步到位,让你少走弯路。 一、全南电工证办理条件你必须知道的3个关键点… · 2026/11/10 23:54:47
工地太忙根本没时间复习考试?官方回应来了,正定电工证培训全攻略 工地太忙根本没时间复习考试?官方回应来了,正定电工证培训全攻略 工地太忙根本没时间复习考试?你不是一个人。尤其是在河北正定这样的工程大县,许多电工从业者都面临类似的困扰。官方回应,针对这种“工学矛盾”,正定电工证培训已推出灵活的线上学习和模… · 2026/11/10 23:54:47
电工证可以兼职用吗良心建议:报名避坑指南与实战分析 电工证可以兼职用吗良心建议:报名避坑指南与实战分析 不知道去哪报名怕被中介坑?现在市面上的电工证培训机构五花八门,价格参差不齐,很多人一不小心就交了冤枉钱。本文是根据 周口地区… · 2026/11/10 23:54:47
高压电工证放电棒全流程办理指南 低压电工证放电棒实操全攻略:三门峡应届生必看的2026河南最新政策 你是不是也担心自己学历不高,考不了高压电工证放电棒?别急,2026年河南最新政策已经明确,低压电工证放电棒的报考条件比你想象的更宽松。这篇文章就帮你理清流程、避坑、了解最新… · 2026/11/10 23:53:47
电工证丢失还能补吗?千万别踩坑,丢了证等于失业 电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/10 2:16:10
电力电缆作业证直播报名入口与办理流程良心建议 电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/10 17:46:39
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/10 17:11:43
丹寨电工证怎么考?内部消息透露报考条件和流程 丹寨电工证怎么考?内部消息透露报考条件和流程 急需特种作业证才能上岗找工作,这是很多电工朋友最真实的焦虑。尤其是像丹寨电工证这样的证书,直接影响你的职业发展和薪资待遇。但你知道吗?很多人都在报考过程中踩坑,有的甚至花了几千块最后白忙一场。今… · 2026/11/10 0:00:13
成都建筑电工证办理郑州报考避坑指南 成都建筑电工证办理郑州报考避坑指南 证书过期了不知道怎么复审延期?别慌!这篇文章手把手带你解决成都建筑电工证办理的难题,顺便避掉郑州报考的那些坑。不管你是刚拿到证的新手,还是准备复审的老电工,这波干货都别错过。… · 2026/11/10 0:00:13
梅州低压电工证怎么考?怕被中介坑?手把手教你全国通用流程 梅州低压电工证怎么考?怕被中介坑?手把手教你全国通用流程 你是不是正为梅州低压电工证发愁?不知道去哪报名,怕被中介骗钱,又担心证书是不是全国通用?其实,这些顾虑都是正常人会有的。今天我就从一个在开封房建工程一线干了几年的电工角度,手把手教你… · 2026/11/10 0:00:13
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 20:19:29
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 19:22:45
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 17:00:47