一、哈希表

哈希表,也称散列表,英文名称Hash Table。是根据关键码值(Key value)而直接进行访问的数据结构,也就是说通过把关键码值映射到表中一个位置来访问记录以便加快查找的速度。这个映射的函数叫做散列函数,存放记录的数组叫做散列表

可以定义为:给定表Table,存在函数F(key),对任意给定的关键字key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表Table为哈希(Hash)表,函数F(key)为哈希(Hash)函数。

二、哈希函数

即哈希函数,也称散列函数,意义:根据关键码值key计算出对应记录的存储位置,position = F(key)。

散列函数满足以下条件:

(1)对输入值运算,得到一个固定长度的摘要(Hash value);

(2)不同的输入值可能产生相同的输出值;

比如:F(x) = x mod 12、F(x) = (x | 0×0000FFFF) XOR (x >> 16)等就可以认为是一个散列函数。同时我们还希望散列函数能满足以下几点:

(1)散列的输出值尽量接近均匀分布;

(2)自变量X的微波变化可以使F(x)发生非常大的变化,即“雪崩效应”;

三、构造Hash函数的方法

(1)直接定址法:哈希函数为关键字的线性函数,H(key) = key 或者 H(key) = a * key + b

此法适于地址集合的大小 == 关键字集合的大小,其中a和b为常数。

(2)数字分析法:假设关键字集合中的每个关键字都是由 s 位数字组成 (u1, u2, …, us),分析关键字集中的全体,并从中提取分布均匀的若干位或它们的组合作为地址

此法适于能预先估计出全体关键字的每一位上各种数字出现的频度

(3)平方取中法: 以关键字的平方值的中间几位作为存储地址。求“关键字的平方值” 的目的是“扩大差别” ,同时平方值的中间各位又能受到整个关键字中各位的影响

此法适于关键字中的每一位都有某些数字重复出现频度很高的现象

(4)折叠法:将关键字分割成若干部分,然后取它们的叠加和为哈希地址。两种叠加处理的方法:移位叠加:将分割后的几部分低位对齐相加;间界叠加:从一端沿分割界来回折叠,然后对齐相加

此法适于关键字的数字位数特别多

(5)除留余数法:设定哈希函数为:H(key) = key MOD p   ( p≤m ),其中, m为表长,p 为不大于 m 的素数,或 是不含 20 以下的质因子

(6)随机数法:设定哈希函数为:H(key) = Random(key)其中,Random 为伪随机函数

此法适于对长度不等的关键字构造哈希函数

实际造表时,不论采用哪种哈希函数构建哈希表,总的原则是使产生冲突的可能性尽可能地小

四、哈希表的冲突处理

由上面的方法可以看到,不论哪种方面总会产生冲突,处理冲突的实际含义是为冲突的关键字寻找下一个哈希地址。

1、开放地址法

这个方法的基本思想是:当发生地址冲突时,按照某种方法继续探测哈希表中的其他存储单元,直到找到空位置为止。这个过程可用下式描述: H i ( key ) = ( H ( key )+ d i ) mod m ( i = 1,2,…… , k ( k ≤ m – 1)) ,其中: H ( key ) 为关键字 key 的直接哈希地址, m 为哈希表的长度, di 为每次再探测时的地址增量。 
采用这种方法时,首先计算出元素的直接哈希地址 H ( key ) ,如果该存储单元已被其他元素占用,则继续查看地址为 H ( key ) + d 2 的存储单元,如此重复直至找到某个存储单元为空时,将关键字为 key 的数据元素存放到该单元。 
增量 d 可以有不同的取法,并根据其取法有不同的称呼:

(1) d i = 1 , 2 , 3 , ……线性探测再散列

(2) d i = 1^2 ,- 1^2 , 2^2 ,- 2^2 , k^2, -k^2……二次探测再散列

(3) d i = 伪随机序列 伪随机再散列,随机探测的基本思想是:将线性探测的步长从常数改为随机数,即令: j = (j + RN) % m ,其中 RN 是一个随机数。在实际程序中应预先用随机数发生器产生一个随机序列,将此序列作为依次探测的步长。这样就能使不同的关键字具有不同的探测次序,从而可以避 免或减少堆聚。基于与线性探测法相同的理由,在线性补偿探测法和随机探测法中,删除一个记录后也要打上删除标记。;

:设有哈希函数 H ( key ) = key mod 7 ,哈希表的地址空间为 0 ~ 6 ,对关键字序列(32 , 13, 49 , 55, 22 , 38, 21 )按线性探测再散列和二次探测再散列的方法分别构造哈希表。 
解:( 1 )线性探测再散列:

32 % 7 = 4 ;

13 % 7 = 6 ;

49 % 7 = 0 ;

55 % 7 = 6 发生冲突,下一个存储地址(6 + 1) % 7 = 0 ,仍然发生冲突,再下一个存储地址:(6 + 2) % 7 = 1 未发生冲突,可以存入;

22 % 7 = 1 发生冲突,下一个存储地址是:( 1 + 1 )% 7 = 2 未发生冲突;

38 % 7 = 3 ;

21 % 7 = 0 发生冲突,按照上面方法继续探测直至空间 5 ,不发生冲突,所得到的哈希表对应存储位置:

下标: 0 1 2 3 4 5 6 49 55 22 38 32 21 13

( 2 )二次探测再散列:

下标: 0 1 2 3 4 5 6 49 22 21 38 32 55 13

注意:对于利用开放地址法处理冲突所产生的哈希表中删除一个元素时需要谨慎,不能直接地删除,因为这样将会截断其他具有相同哈希地址的元素的查找地址,所以,通常采用设定一个特殊的标志以示该元素已被删除。

2、拉链法

拉链法解决冲突的做法是:将所有关键字为同义词的结点链接在同一个单链表中。若选定的散列表长度为m,则可将散列表定义为一个由m个头指针组成的指针数 组T[0..m-1]。凡是散列地址为i的结点,均插入到以T[i]为头指针的单链表中。T中各分量的初值均应为空指针。在拉链法中,装填因子α可以大于 1,但一般均取α≤1。

3、再哈希法

这种方法的思想是同时构造多个不同的哈希函数:H1=RH1(key) i=1,2,3...,k。当哈希地址Hi=RH1(key)发生冲突时再计算Hi=RH2(key)...,直到冲突不再产生。这种方法不易产生聚焦,但增加了计算时间。

转自:https://blog.csdn.net/u012050154/article/details/50782809

哈希表存在的问题及解决方案相关推荐

  1. 二叉树和哈希表的优缺点对比与选择

    二叉树(binary tree)和哈希表(hash table)都是很基本的数据结构,但是我们要怎么从两者之间进行选择呢?他们的不同是什么?优缺点分别是什么? 回答这个问题不是一两句话可以说清楚的,原 ...

  2. 哈希表及哈希函数研究综述

    哈希表及哈希函数研究综述 摘要 随着信息化水平的不断提高,数据已经取代计算成为了信息计算的中心,对存储的需求不断提高信息量呈现爆炸式增长趋势,存储已经成为急需提高的瓶颈.哈希表作为海量信息存储的有效方 ...

  3. 数据结构与算法五:哈希表-哈希函数设计原则-哈希冲突解决方案

    一.哈希表的定义: 二.哈希表举例: 哈希函数就是映射关系 三.哈希表应用举例: Leetcode上第387题: 思路:通过s.charAt(i)-'a'将字符串中的字符映射成hash表,出现一次,在 ...

  4. PHP哈希表碰撞攻击原理

    哈希表碰撞攻击(Hashtable collisions as DOS attack)的话题不断被提起,各种语言纷纷中招.本文结合PHP内核源码,聊一聊这种攻击的原理及实现. 哈希表碰撞攻击的基本原理 ...

  5. 10.LeetCode第九题--有效的数独--哈希表的经典应用

    思路 一个简单的解决方案是遍历该 9 x 9 数独 三 次,以确保: 行中没有重复的数字. 列中没有重复的数字. 3 x 3 子数独内没有重复的数字. 实际上,所有这一切都可以在一次迭代中完成. 方法 ...

  6. 哈希表(HASHTABLE)

    原文地址:http://www.cnblogs.com/abatei/archive/2009/06/23/1509790.html C#中实现了哈希表数据结构的集合类有: (1) System.Co ...

  7. 哈希表的C实现(三)---传说中的暴雪版

    关于哈希表C实现,写了两篇学习笔记,不过似乎网上流传最具传奇色彩的莫过于暴雪公司的魔兽文件打包管理器里的hashTable的实现了:在冲突方面的处理方面,采用线性探测再散列.在添加和查找过程中进行了三 ...

  8. 【从蛋壳到满天飞】JS 数据结构解析和算法实现-哈希表

    前言 [从蛋壳到满天飞]JS 数据结构解析和算法实现,全部文章大概的内容如下: Arrays(数组).Stacks(栈).Queues(队列).LinkedList(链表).Recursion(递归思 ...

  9. hashmap是散列表吗_一篇文章教你读懂哈希表-HashMap

    题图Pid=68670770 在最近的学习过程中,发现身边很多朋友对哈希表的原理和应用场景不甚了解,处于会用但不知道什么时候该用的状态,所以我找出了刚学习Java时写的HashMap实现,并以此为基础 ...

最新文章

  1. 语言中knitr_R语言软件包的批量引用
  2. Java 洛谷 P1200 [USACO1.1]你的飞碟在这儿 Your Ride Is Here
  3. 校讯通近期爆发短信诈骗:取消不可能 那如何规范
  4. python tqdm进度条打印
  5. Insomni'hack teaser 2019 - Misc - curlpipebash
  6. AUTOSAR从入门到精通100讲(二十)-AUTOSAR通信篇—CanIf模块
  7. ie6 offsetWidth/offsetHeight无效
  8. Python 第三方模块之 psutil - 获取系统运行的进程和系统利用率信息
  9. GCC选项_-Wl,-soname 及 DT_NEEDED 的解释
  10. php ftp login,关于php ftp_login()函数的10篇文章推荐
  11. [转]在EntityFramework6中执行SQL语句
  12. koa2异常处理_koa2 中的错误处理以及中间件设计原理
  13. python免费领取视频-quot;免费领取Python资源”
  14. 开始编译mysql文件_mysql编译安装(详细)(转载)
  15. 单片机应用系统设计技术——串行口方式0 拓展并行输出端口 02 74LS164芯片
  16. 计算机自动开机关机设置在哪里设置密码,怎样设置开关机密码
  17. 解决Windows因更新导致C盘容量急剧减少
  18. CRC16_CCITT/True的Java计算实现
  19. word一行内英文单词之间间隔过大解决方法
  20. 搭建easy-mock数据模拟服务器

热门文章

  1. MySQL中如何定义外键[转]
  2. F#基本类型——Records
  3. 删除以x为根节点的子树并释放☆
  4. 诗与远方:无题(七十)- 小熊熬夜记
  5. antv图例出现分页_图例-自定义文本样式
  6. 不小心合并了icloud通讯录_苹果手机怎么恢复通讯录联系人号码?原来方法竟如此简单!...
  7. 微信小程序自定义组件4 —— 代码共享behaviors
  8. 负载均衡的几种方式_负载均衡的几种方式
  9. eclipse php 环境及调试配置
  10. 为5—18岁青少年提供营地教育,漫族完成百万级天使轮融资