上一章中,我们使用了双重Hash的技术来处理碰撞,并用了C语言实现,本章我们将实现Hash表中的插入搜索删除接口。

实现接口

我们的hash函数将会实现如下的接口:

// hash_table.h
void ht_insert(ht_hash_table* ht, const char* key, const char* value);
char* ht_search(ht_hash_table* ht, const char* key);
void ht_delete(ht_hash_table* ht, const char* key);

Insert函数

hash表中插入一条记录时,我们需要遍历整个hash表知道找到一个空的位置,然后执行插入并将hash表的大小加1hash表中的count属性代表hash表的大小,在下一章缩放hash表大小中很有用:

void ht_insert(ht_hash_table* ht, const char* key, const char* value) {ht_item* item = ht_new_item(key, value);int index = ht_get_hash(item->key, ht->size, 0);ht_item* cur_item = ht->items[index];int i = 1;while(cur_item != NULL) {index = ht_get_hash(item->key, ht->size, i);cur_item = ht->items[index];++i;}ht->items[index] = item;ht->count++;
}

Search函数

searchinsert有点相似,但是在while循环中,我们会检查记录的key是否与我们正在搜索的key匹配。如果匹配,就会返回这条记录的value,没有匹配到就会返回NULL

char* ht_search(ht_hash_table* ht, const char* key) {int index = ht_get_hash(key, ht->size, 0);ht_item* item = ht->items[index];int i = 1;while (item != NULL) {if (strcmp(item->key, key) == 0) {return item->value;}index = ht_get_hash(key, ht->size, i);item = ht->items[index];i++;} return NULL;
}

delete函数

从开放的地址hash表中删除比插入或搜索更复杂,因为存在碰撞,我们希望删除的记录可能是碰撞链的一部分。从表中删除它会破坏该链,并且无法在链的尾部找到记录。要解决此问题,我们只需将其标记为已删除,而不是真的删除该记录。

我们将记录替换为指向全局哨兵的指针,再将其标记为已删除,该全局哨兵表示包含已删除的记录的bucket

// hash_table.c
static ht_item HT_DELETED_ITEM = {NULL, NULL};void ht_delete(ht_hash_table* ht, const char* key) {int index = ht_get_hash(key, ht->size, 0);ht_item* item = ht->items[index];int i = 1;while (item != NULL) {if (item != &HT_DELETED_ITEM) {if (strcmp(item->key, key) == 0) {ht_del_item(item);ht->items[index] = &HT_DELETED_ITEM;}}index = ht_get_hash(key, ht->size, i);item = ht->items[index];i++;} ht->count--;
}

删除后,我们需要将hash表count属性减1

我们也需要修改下ht_insertht_search函数,当搜索时,我们需要忽略并跳过已删除的项,在已删除项的位置我们可以插入新的记录:

// hash_table.c
void ht_insert(ht_hash_table* ht, const char* key, const char* value) {// ...while (cur_item != NULL && cur_item != &HT_DELETED_ITEM) {// ...}// ...
}char* ht_search(ht_hash_table* ht, const char* key) {// ...while (item != NULL) {if (item != &HT_DELETED_ITEM) { if (strcmp(item->key, key) == 0) {return item->value;}}// ...}// ...
}

修改一下

我们的hash表现在还不支持更新key的值,如果我们插入两条相同key的记录,key将会冲突,第二条记录就会插入到下一个可用的位置,当使用key搜索时,我们会找到第一条记录,第二条记录就永远不会被找到,现在我们修改下ht_insert函数,在插入多条相同key的记录时,会删除之前的记录再插入新的记录:

// hash_table.c
void ht_insert(ht_hash_table* ht, const char* key, const char* value) {// ...while (cur_item != NULL) {if (cur_item != &HT_DELETED_ITEM) {if (strcmp(cur_item->key, key) == 0) {ht_del_item(cur_item);ht->items[index] = item;return;}}// ...} // ...
}

上一章:处理碰撞
下一章:缩放Hash表大小

[译]C语言实现一个简易的Hash table(5)相关推荐

  1. [译]C语言实现一个简易的Hash table(3)

    上一章,我们讲了hash表的数据结构,并简单实现了hash表的初始化与删除操作,这一章我们会讲解Hash函数和实现算法,并手动实现一个Hash函数. Hash函数 本教程中我们实现的Hash函数将会实 ...

  2. 十位数连加 c语言,用C语言编写一个简易计算器可实现加减乘除,连加连减,连乖连除....

    用C语言编写一个简易计算器可实现加减乘除,连加连减,连乖连除. 用C语言编写一个简易计算器可实现加减乘除,连加连减,连乖连除. 人气:435 ℃时间:2020-04-10 06:55:13 优质解答 ...

  3. 用go语言撸一个简易版的区块链

    用go撸一个简易版的区块链 引言 这个最初的版本时多年以前学习go的时候,自己撸的一个简易版本的区块链.不过麻雀虽小,五脏俱全.通过这个代码你了解区块链内部的大概运行机制时没有问题的. 比特币底层区块 ...

  4. C语言-实现一个简易的银行排号叫号系统

    这两天在网上看到这个题目,感觉挺有意思,就做了一下.我在网上看到其他人都是用C++做的,因为不懂C++语言,没看懂,尝试着用C语言做了该题.希望能来看该题的大神指点指点,估计还有些bug没找出来. 本 ...

  5. 使用java语言编写一个简易的计算器(完整代码与详细步骤都有哦!)

    [案例介绍] 1.案例描述 本案例要求利用Java Swing 图形组件开发一个可以进行简单的算术运算的图形化计算器. 2.运行结果 运行结果 [案例目标] 学会分析"简易计算器" ...

  6. 用C语言设计一个简易的选择题答题系统

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.设计简易的答题系统 二.使用步骤 1.引入库 2.读入数据 总结:应用随机数,getchar以及if else 前 ...

  7. 用java编写一个简易功能画板_用Java语言编写一个简易画板

    讲了三篇概博客的概念,今天,我们来一点实际的东西.我们来探讨一下如何用Java语言,编写一块简易的画图板. 一.需求分析 无论我们使用什么语言,去编写一个什么样的项目,我们的第一步,总是去分析这个项目 ...

  8. 使用Java语言搭建一个简易的局域网直播(live)系统

    演示一下 局域网直播系统,顾名思义是运行在局域网中的系统,整个直播系统由两部分构成:录制和播放,核心思路是推拉流和流转码. 录制直播 录制直播使用的是自己电脑的摄像头和麦克风,使用Java自带的JFr ...

  9. 用c语言编写一个简易的编译器,面向教学的简易c语言编译器的设计与实现(54页)-原创力文档...

    目录 TOC \o "1-5" \h \z \o "Current Document" 摘要I ABSTRACTII \o "Current Docu ...

  10. C语言编写一个简易的网络词典

    摘要:电子辞典是指将传统的辞典中的内容转换为数字格式存储的文件,并且将它们保存在存储器中.用户使用时只需要通过键盘输入需要查询的条目,电子辞典通过自身携带的处理器,按照一定的编码查询方式便可以找到相关 ...

最新文章

  1. 基于深度学习OpenCV与python进行字符识别
  2. Count the Colors ZOJ - 1610
  3. 深度学习(一)——MP神经元模型, BP算法, 神经元激活函数, Dropout
  4. c 写c语言代码编辑器,最好用的c/cpp代码编辑器是vim,没有之一
  5. 页面级缓存@ OutputCache
  6. 将CloudWatch Logs与Cloudhub Mule集成
  7. xss原理和注入类型
  8. 创造黑科技,守护新未来 | 360公司2019年春季校园招聘正式启动!
  9. android唯一机器码生成方案_分布式系统唯一ID生成方案汇总
  10. 安装php-zbarcode的步骤方法
  11. 三星i9158刷机教程
  12. Android测试之Robotium自动化测试框架
  13. 团队管理13--设定工作目标
  14. 用matlab求系统幅度频率响应,matlab频率响应
  15. 2022最新批量删除微博教程!支持批量删除微博批量删除清空点赞关注评价以及粉丝
  16. python爬虫:爬取新浪新闻数据
  17. java web 站内信 设计
  18. 魔芋粉的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  19. Android5.1--PowerManagerService电源管理
  20. 天线为什么会有多次谐振_如果天线不处于谐振状态,辐射效率会受到多大影响?...

热门文章

  1. Ibatis -- 一次执行多条SQL
  2. 初识B/S结构编程技术
  3. 【Android】proguard混淆代码
  4. Android手机root概念
  5. 语录(心灵鸡汤来一波)
  6. 写函数,输入n个数字输出最大值和最小值
  7. 白鹭引擎和layabox哪个好用,哪个技术更成熟 ?
  8. 洛谷P1978 集合 [2017年6月计划 数论08]
  9. ubuntu14.04 pygame安装 python2.7
  10. 学习笔记——RuntimeException