散列表(hash table): 也称为哈希表. 根据wikipedia的定义:是根据关键字(Key value)而直接访问在内存存储位置的数据结构。也就是说,它通过把键值通过一个函数的计算,映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数(hash function),存放记录的数组称做散列表(hash table)

为了方便理解概念.举个与散列表原理相似的实际生活中应用例子--电话簿.一般的电话簿是按照电话用户的姓的首字母a-z顺序进行排列的,首字母相同的按照姓的第二个字母进行排列,以此类推(可能还有其他的规则,比如地点,时间,或者几种规则的混合).当我们要查找某人的电话号码时,我们会根据用户的姓推导出对应的首字母,然后再按照首字母去对应的子目录下查找和该用户姓名对应的电话号码.在这个过程中,"用户的姓名"对应于散列表中的关键字(key),"推导的规则"好比散列表中的哈希函数(hash function).号码簿即散列表. 散列表是根据将关键字代入哈希函数中求得的值进行存储,而非根据关键字. 那就有会存在这样的一种情况,如果将不同的关键字代入哈希函数求得的值相同,那散列表如何处理呢? 这种不同关键字而哈希函数值相同的情况称作碰撞(collision).

对于散列表的设计,建立以及建立后数据的查找,插入和删除等操作的性能,问题的重心主要在两个方面:哈希函数和碰撞。

哈希函数:

对于一个好的哈希函数来讲,每个关键字都等可能地分配到m(假设散列表提供了m个槽位(slot))的槽位中,并且与其他关键字已经分配到哪个槽位无关。确切来讲要求该函数是符合独立同分布的特点。但是在实际中,我们很难找出关键字的分布规律. 一种好的方法是以独立于数据中可能存在的任何模式的方法导出散列值(算法导论 第二版). 对于这句话我的理解是: 在实际产生的数据中,数据的内容,格式等很大程度上可能存在着联系和聚集的情况, 即分布不均匀, 而散列表顾名思义,需要"散列",如果采用数据原有的模式如内容,格式等与"散列"的精神冲突的可能性很大.

下面介绍几种哈希函数的设计方案:

将关键字解释为自然数: 我们都知道计算机的灵魂只有"0"和"1", 与它们比较接近的是数字,或者更小范围的整数,自然数. 如果能够将信息或数据转化为自然数,计算机处理数字要方便的多. 同时对于哈希函数来讲,处理数字更便利.基于这两点,散列表要求的关键字,我们可以将原始关键字进行转化自然数形式.

1.除法散列法

散列函数: h(k)= k mod m

m: 散列表槽数  k:关键字   h(k): 数组地址索引

函数关键: m 的选择,一般选择与2的整数次幂不太接近的质数

2. 乘法散列表

散列函数: 

两个步骤:

1. 用关键字k乘上常数A(0<k<1), 取出kA的小数部分。

2. 用m乘以这个小数部分,再对乘积的结果取底。

优点: 对于m的取值没有太多的要求,一般选择以2为底的某个次幂。 A的取值为0.618 033 比较理想。

无论怎么设计哈希函数,对于"碰撞"情况的发生都是不能绝对避免的,所以接下来的问题是怎么解决"碰撞"的情况. 现在普遍的方法有链接法,和开放寻址法.下面阐述的炒作都忽略卫星数据,只考虑关键字。

链接法:

顾名思义,是通过链表将碰撞的数据进行相互链接到同一槽上. 对于插入,删除,查找操作,在完成查找对应槽的操作后(O(1)),接下来的既是对链表进行操作。假设有n个关键字,m 条槽

成功查找:O(1+n/m), 失败查找:O(1+n/m)

插入有不同的规则, 一般是插入到链表头部(即与槽相连接部分).

开放寻址法:

将所有的元素都存入到散列表中,不通过链表来解决碰撞问题,如果产生碰撞,通过改变参数来使用哈希函数中重新寻找空槽. 由于要求所有元素都存入散列表中,这就需要n<=m,及关键字总数小于槽数。

优点: 不需要使用指针,节省了空间,潜在的效果是减少碰撞,提高了查找速度。

插入: 对于每一个关键字k, 都可以按照如下的序列<h(k,0),h(k,1)...h(k,n-1)>,依次进行,直到查找到空槽插入关键字为止.

查找: 和插入算法是一样的,只是查找过程中如果碰到一个空槽就停止,返回信息

删除: 由于查找的规则,所以删除一项时,应该将该空槽进行标记,如Deleted

散列表(Hash Table)的更多相关文章

  1. [转载] 散列表(Hash Table)从理论到实用(上)

    转载自:白话算法(6) 散列表(Hash Table)从理论到实用(上) 处理实际问题的一般数学方法是,首先提炼出问题的本质元素,然后把它看作一个比现实无限宽广的可能性系统,这个系统中的实质关系可以通 ...

  2. [转载] 散列表(Hash Table)从理论到实用(中)

    转载自:白话算法(6) 散列表(Hash Table)从理论到实用(中) 不用链接法,还有别的方法能处理碰撞吗?扪心自问,我不敢问这个问题.链接法如此的自然.直接,以至于我不敢相信还有别的(甚至是更好 ...

  3. [转载] 散列表(Hash Table) 从理论到实用(下)

    转载自: 白话算法(6) 散列表(Hash Table) 从理论到实用(下) [澈丹,我想要个钻戒.][小北,等等吧,等我再修行两年,你把我烧了,舍利子比钻戒值钱.] ——自扯自蛋 无论开发一个程序还 ...

  4. Java 集合 散列表hash table

    Java 集合 散列表hash table @author ixenos 摘要:hash table用链表数组实现.解决散列表的冲突:开放地址法 和 链地址法(冲突链表方式) hash table 是 ...

  5. 散列表(Hash table)及其构造

    散列表(Hash table) 散列表,是根据关键码值(Key value)而直接进行访问的数据结构.它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录 ...

  6. 散列表(hash table)——算法导论(13)

    1. 引言 许多应用都需要动态集合结构,它至少需要支持Insert,search和delete字典操作.散列表(hash table)是实现字典操作的一种有效的数据结构. 2. 直接寻址表 在介绍散列 ...

  7. 算法导论-散列表(Hash Table)-大量数据快速查找算法

    目录 引言 直接寻址 散列寻址 散列函数 除法散列 乘法散列 全域散列 完全散列 碰撞处理方法 链表法 开放寻址法 线性探查 二次探查 双重散列 随机散列 再散列问题 完整源码(C++) 参考资料 内 ...

  8. 白话算法(6) 散列表(Hash Table)从理论到实用(中)

    不用链接法,还有别的方法能处理碰撞吗?扪心自问,我不敢问这个问题.链接法如此的自然.直接,以至于我不敢相信还有别的(甚至是更好的)方法.推动科技进步的人,永远是那些敢于问出比外行更天真.更外行的问题, ...

  9. 白话算法(6) 散列表(Hash Table)从理论到实用(上)

    处理实际问题的一般数学方法是,首先提炼出问题的本质元素,然后把它看作一个比现实无限宽广的可能性系统,这个系统中的实质关系可以通过一般化的推理来论证理解,并可归纳成一般公式,而这个一般公式适用于任何特殊 ...

随机推荐

  1. css背景属性整理

    背景颜色 {background-color:red}/*常用十六进制颜色#fff*/ 图片 {background-image:url();} /*插入图片路径*/ 重复 {background-r ...

  2. Webpack构建前端项目

    前言 公司据说要搞前后端分离,趁这两天项目完成的差不多,抓紧时间学习一下前端知识 现在流行前端项目工程化,那么第一个问题就是如何创建工程(项目),第一次玩webpack 通过 NPM 创建项目 # 创 ...

  3. ubuntu下编译安装poco

    系统环境: ubuntu版本:Linux jfcai-VirtualBox 4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018 ...

  4. 2019.10.25 csp-s模拟测试87 反思总结

    一次非常神奇的考试,考完试以后看着T2的0pts突然笑死我自己 太智障了这什么神奇的题意理解错误23333 T1一眼分类讨论,两眼二分,觉得分类讨论有点玄学但是出题人八成不会卡[何],然后本着对二分的 ...

  5. js 获取复选框 和 并改变状态

    function checkAll() { var checkbox = document.getElementById('vegeids');// var boxes = document.getE ...

  6. 第03章 科学计算库Numpy

    016.Numpy数据结构    关于矩阵运算的库 矩阵 017.Numpy基本操作 判断每一个元素的 018.Numpy矩阵属性 019.Numpy矩阵操作 020.Numpy常用函数 按列拼接就用 ...

  7. 2019阿里云开年Hi购季大促主会场全攻略!

    2019阿里云云上采购季活动已经于2月25日正式开启,从已开放的活动页面来看,活动分为三个阶段: 2月25日-3月04日的活动报名阶段.3月04日-3月16日的新购满返+5折抢购阶段.3月16日-3月 ...

  8. linux中tab键不能补全,却能切换窗口

    linux中所有程序-设置-窗口管理器-键盘-切换同一应用程序的窗口-清除

  9. jQuery事件绑定的四种方法

    jQuery中提供了四种绑定事件的方法,分别是bind.live.delegate.on,对应的解除监听的函数分别是unbind.die.undelegate.off: 一.on()方法(首选方法) ...

  10. 对BOM的总结

    参考:JavaScript半知半解 TG著 BOM对象 Window对象是客户端JavaScript程序的全局对象. Window对象使得JavaScript与浏览器进行交互. 所有的JavaScri ...