上一章我们讲了如何根据需要动态设置hash表的大小,在第四章中,我们使用了双重哈希来解决hash表的碰撞,其实解决方法有很多,这一章我们来介绍下其他方法。

本章将介绍两种解决hash表碰撞的方法:

  1. 拉链法
  2. 开放地址法

拉链法

使用拉链法,每一个bucket都会包含一个链接表,当发生碰撞时,就会将该记录插入在该位置的链接表后面,步骤如下:

  • 插入时:通过hash函数获取到要插入的位置,如果该位置是空的,就直接插入,如果该位置不是空的,就插入在链接表的后面

  • 搜索时:通过hash函数获取到key对应的位置,遍历链接表,判断key是不是搜索的key,如果是,则返回value,否则返回NULL

  • 删除时:通过hash函数获取到key对应的位置,遍历链接表,找到需要删除的key,如果找到,则将该key对应的记录从链接表中删除,如果链接表中只有一条记录,则将该位置置为NULL

拉链法的优点是实现起来简单,但是空间利用率低。每个记录必须存储指向链接表中下一个记录的指针,如果没有记录,则指向NULL,这种方法会浪费一些空间来存储额外的指针。

开放地址法

开放地址法能解决拉链法空间利用率低的问题,发生碰撞时,碰撞的记录将放置在hash表中的其他bucket中,存放的位置是根据预先确定的规则选择的,以便在搜索记录时可以重复该规则,有如下几种规则:

线性探查

当发生碰撞时,就会递增索引,将记录插入在下一个可用的索引中,方法如下:

  • 插入时:通过hash函数找到插入的位置的索引,如果这个位置是空的,直接插入,如果不为空,就递增索引,直到找到索引指向的位置是空的为止,然后执行插入

  • 搜索时:通过hash函数找到搜索的记录的索引,每次递增索引,并比较索引指向的值是否是要搜索的值,如果索引指向的是空,则返回NULL

  • 删除时:通过hash函数找到删除的记录的索引,每次递增索引,直到找到要删除的那个key后执行删除

线性探测提供了良好的缓存性能,但是存在碰撞后遍历次数多的问题。将发生碰撞的key放入下一个可用的bucket中可能导致后面插入记录也要往后插,就需要多次迭代。

二次探查

二次探查法和先行探查类似,不同的是,发生碰撞后,我们会将记录插入在如下的序列中:i, i + 1, i + 4, i + 9, i + 16, ...,i代表通过hash函数获取到的索引,具体步骤如下:

  • 插入时:通过hash函数找到插入的索引,通过遍历上面的序列直到找到一个空的或已被删除的索引位置,执行插入

  • 搜索时:通过hash函数找到key的索引,遍历上面的序列,将序列上的key与搜索的key对比,如果相等,则返回value,否则返回NULL

  • 删除时:因为我们无法判断要删除的项是不是碰撞链上的,所以我们不能直接删除该条记录,只能把它标记为已删除

二次探查法减少发生碰撞后遍历的次数,并且仍然提供了不错的缓存性能。

双重hash

双重hash旨在解决碰撞后遍历次数多的问题。使用两次hash函数为插入的记录选择新的索引,这个索引会均匀的分布在整个表中,该方法虽然解决了上述问题,但也失去了缓存特性,双重hash是实际项目中常见的冲突管理方法,也是我们在本教程中实现的方法。

上一章:设置hash表大小


原文地址:https://github.com/jamesroutley/write-a-hash-table/tree/master/07-appendix

[译]C语言实现一个简易的Hash table(7)的更多相关文章

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

    上一章我们解释了Hash table中最重要的hash函数,并用伪代码和C语言实现了一个我们自己的hash函数,hash函数中碰撞是无法避免的,当发生碰撞时我们改如何有效的处理呢?这章我们就来讲解下. ...

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

    说明 Hash table翻译过来就是Hash表,是一种提供了类似于关联数组的数据结构,可以通过key执行搜索.插入和删除操作.Hash表由一些列桶(buckets)组成,而每一个bucket都是由k ...

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

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

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

    上一章,简单介绍了Hash Table,并提出了本教程中要实现的几个Hash Table的方法,有search(a, k).insert(a, k, v)和delete(a, k),本章将介绍Hash ...

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

    上一章中,我们使用了双重Hash的技术来处理碰撞,并用了C语言实现,贲张我们将实现Hash表中的插入.搜索和删除接口. 实现接口 我们的hash函数将会实现如下的接口: // hash_table.h ...

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

    上一章中,我们实现了Hash表中的插入.搜索和删除接口,我们在初始化hash表时固定了大小为53,为了方便扩展,本章将介绍如何修改hash表的大小. 设置Hash表大小 现在,我们的hash表是固定大 ...

  7. 用Java语言编写一个简易画板

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

  8. 用java语言写一个简易版本的登录页面,包含用户注册、用户登录、用户注销、修改密码等功能

    package com.Summer_0421.cn; import java.util.Arrays; import java.util.Scanner; /** * @author Summer ...

  9. PHP内核探索之变量(3)- hash table

    在PHP中,除了zval, 另一个比较重要的数据结构非hash table莫属,例如我们最常见的数组,在底层便是hash table.除了数组,在线程安全(TSRM).GC.资源管理.Global变量 ...

随机推荐

  1. Anaconda管理多版本的python环境

    通过Conda的环境管理功能,我们能同时安装多个不同版本的Python,并能根据需要自由切换.下面我将给大家分享一下,新增Python版本,切换,再切回主版本的详细过程. 方法/步骤   1 首先确保 ...

  2. Oracle案例09——ORA-12154: TNS:could not resolve the connect identifier specified

    DG处理的问题还是蛮多的,但这次遇到一个比较奇葩的事情,表面配置.网络都没啥问题,但主备的同步始终有问题,经过多次调整参数.重新部署问题依旧,最终还是求助mos问题得以解决,现将处理过程记录如下: 一 ...

  3. [翻译] GTAppMenuController

    GTAppMenuController https://github.com/gianlucatursi/GTAppMenuController This is a simple project in ...

  4. Redis 集群缓存测试要点--关于 线上 token 失效 BUG 的总结

    在测试账户系统过程中遇到了线上大面积用户登录态失效的严重问题,事后对于其原因及测试盲点做了一些总结记录以便以后查阅,总结分为以下7点,其中原理性的解释有些摘自网络. 1.账户系统token失效问题复盘 ...

  5. Compare DML To Both REDO And UNDO Size

    SUMMARY you can remember undo rule  the same to redo if you want demo rule that you can look up the ...

  6. 为Linux设置IPTables防火墙

    我们 来讨论一下如何为你的CentOS 服务器来设置简单的防火墙. 这里我们以DigitalOcean的CentOS 6 VPS为基础来讨论的,同样也适用于 阿里云上其他类型的LINUX系统. (阿里 ...

  7. Maximum Flow and Minimum Cut

    最大流最小割 Introduction Mincut Problem 最小割问题,输入是带权有向图,有一个源点 s(source)和一个汇点 t(target),边的权重在这里称作容量(capacit ...

  8. [T-ARA][TIAMO]

    歌词来源:http://music.163.com/#/song?id=439915067 改了一版格式,先尝试一下,考虑到总不能永远只看着拼音读,所以想把发音按照韩文字来写,以后争取看着韩文字唱. ...

  9. Python错误和异常概念(总)

    转载请标明出处: http://www.cnblogs.com/why168888/p/6435956.html 本文出自:[Edwin博客园] Python错误和异常概念(总) 1. 错误和异常的处 ...

  10. c++抽象类,纯虚函数