PHP数据结构(十五) ——哈希表​

PHP数据结构(十五)——哈希表

(原创内容,转载请注明来源,谢谢)

一、概述

查找的效率与查找的次数有关,查找的次数越少速度越快。因此,希望能够一次查找出结果,此时键值一一对应,称满足这条件的f(k)为哈希函数。

1、定义

1)冲突

不同的关键字通过哈希函数,得到同一个地址,称为冲突。具有相同函数值的关键字称为同义词。

2)哈希表

根据设定的哈希函数H(key)和处理冲突的方法,将一组关键字映像到一个有限连续的地址集上,以关键字的“像”作为记录的位置,此表称为哈希表,映像过程称为哈希造表或散列,所得存储位置称哈希地址或散列地址。

2、性质

哈希函数是一个映像,设定灵活,任何关键字由此所得的哈希值落在表长允许范围内。

二、构造哈希表

对于关键字集合中的任意一个关键字,经哈希函数映像到地址集合中的任一地址的概率是相等的,称为均匀的哈希表。

1、直接定址法

取关键字或某个线性函数作为哈希地址,即H(key)=key,或(key)=a*key+b(a、b都是常数)。

该方法地址集合和关键字的大小一样,不会有冲突,但是实际上很少用到。

2、数字分析法

此方法适用于能够预先估计到全部的结果。假设关键字是以R为基的数(例如R=10的十进制),且可以知道哈希表的所有值,则可以用关键字的一部分组成哈希地址。

例如,10000-10099,可以用key0-99来表示。

3、平方取中法

取关键字平方和的中间几位作为地址。此方法类似数字分析法,将关键字进行平方的目的是拉大两个关键值之间的差距。该方法较为常用。因为平方之后的中间几位和这个数的每个数字都有关,具体位数由表长决定。

4、折叠法

将关键字分割成几部分,这几部分叠加和(舍去进位)作为哈希地址。当关键字很长,且分布均匀时,可以采用此方法。

5、除留余数法

取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。

即H(key)=keyMOD p(p<=m),该方法比较简单,而且可以结合折叠、平方取中等方式。但是要注意,选的数不能太小,也最好不要有很多因数,否则有可能取出来的余数相同的太多。最好选择20以上的质数来取余。

6、随机数法

选择一个随机数,取关键字的随机函数值为它的哈希地址,即H(key)=random(key)。通常,当关键字长度不等时采用此法构造哈希函数比较恰当。

三、构造过程需要考虑的因素

1、计算哈希函数所需的时间,包括硬件指令的因素。

2、关键字的长度。

3、哈希表的大小。

4、关键字的分布情况。

5、记录查找的频率。

四、冲突处理方法

使用哈希函数,很有可能会出现冲突,即多个数经过哈希函数得到同一个结果。此时,就需要冲突处理方法,来使得发生冲突的关键字能够得到一个单独的映射结果。冲突处理方法,用符号Hi表示。

1、开放定址法

发生冲突的哈希值,加上一个数,在取余,可以得到另一个结果,可以作为冲突解决的方式,即:

Hi= ( H(key) + di ) MOD m (i=1,2…k)(k<=m-1)。其中,H(key)为哈希函数,m为哈希表表长,di为增量序列,可以有以下三种取法:

1)线性探测再散列,di=1,2,3…m-1

2)二次探测再散列,di=1,-1,4,-4,9,-9…(m/2)2

3)伪随机数序列

以上三种结果各有好坏。

1)使用线性探测再散列,可以理解为取点i作为哈希值,如果发生冲突,就取i+1,如果还冲突,就取i+2。这样可以保证,只要哈希表还有空间,就一定能够取得哈希值。但是,这样速度会比较慢,特别是比较密集的区间,可以要连续做好几次的冲突处理才可以得到一个结果。

2)使用二次探测再散列,速度将比较快,因为其是采用平方的方式,而不是逐一递增,因此在经过i次的查找,其查找的范围达到i2,这样有效跳出一个大范围的区间。但是,因为这个方式不是逐一取结果,因此有可能最终没有找到能使用的哈希值。

3)伪随机数是随机的数,则结果不稳定,有可能特别快,也有可能特别慢。

2、再哈希法

Hi=RH(key)。即发生冲突时,换一种冲突处理方式,来解决冲突。

3、链地址法

该方法取得的哈希值键值不是一一对应的,而是一个哈希值指向一个存储空间,该空间是一个线性链表,由所有哈希结果一致的键组成。该方式可以保证哈希的结果足够快,不需要进行再哈希或者开放地址计算,也能保证每一个键一定可以有哈希值。但是,查找的时候相对速度较慢,因为需要在链表里面逐一判断结果。

4、建立公共溢出区

该方式为补救措施,即建立一个公共的区域,所有无法取得哈希的结果都放在此区域。该方式获取结果效率会比较低,但是作为补救措施,可以保证数据不丢失。

——written by linhxx 2017.07.15

相关阅读:

PHP数据结构(十四) ——键树(双链树)

PHP数据结构(十三) ——动态查找表(二叉排序树)

PHP数据结构(十二) ——静态查找表​

PHP数据结构(十一) ——图的连通性问题与最小生成树算法(2)

PHP数据结构(十一) ——图的连通性问题与最小生成树算法(1)

PHP数据结构(十) ——有向无环图与拓扑算法

PHP数据结构(九) ——图的定义、存储与两种方式遍历

PHP数据结构(八) ——赫夫曼树实现字符串编解码(实践2)

PHP数据结构(八) ——赫夫曼树实现字符串编解码(实践1)

PHP数据结构(八) ——赫夫曼树实现字符串编解码(理论)

PHP数据结构(七) ——串与实现KMP算法

PHP数据结构(六) ——树与二叉树之概念及存储结构

PHP数据结构(六) ——数组的相乘、广义表

PHP数据结构(五) ——数组的压缩与转置

PHP数据结构(四) ——队列

PHP数据结构(三)——运用栈实现括号匹配

PHP数据结构(二)——链式结构线性表

PHP数据结构(一)——顺序结构线性表

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-07-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一个爱瞎折腾的程序猿

sqlserver使用存储过程跟踪SQL

USE [master] GO /****** Object: StoredProcedure [dbo].[sp_perfworkload_trace_s...

2210
来自专栏闻道于事

js登录滑动验证,不滑动无法登陆

js的判断这里是根据滑块的位置进行判断,应该是用一个flag判断 <%@ page language="java" contentType="text/html...

7238
来自专栏飞扬的花生

jsencrypt参数前端加密c#解密

      写程序时一般是通过form表单或者ajax方式将参数提交到服务器进行验证,如何防止提交的请求不被抓包后串改,虽然无法说绝对安全却给非法提交提高了难度...

3939
来自专栏落花落雨不落叶

canvas画简单电路图

66411
来自专栏菩提树下的杨过

Flash/Flex学习笔记(23):运动学原理

先写一个公用的小球类Ball: package{ import flash.display.Sprite; //小球 类 public class B...

25410
来自专栏一个会写诗的程序员的博客

Spring Reactor 项目核心库Reactor Core

Non-Blocking Reactive Streams Foundation for the JVM both implementing a Reactiv...

2242
来自专栏我和未来有约会

Kit 3D 更新

Kit3D is a 3D graphics engine written for Microsoft Silverlight. Kit3D was inita...

2636
来自专栏张善友的专栏

LINQ via C# 系列文章

LINQ via C# Recently I am giving a series of talk on LINQ. the name “LINQ via C...

2675
来自专栏hbbliyong

WPF Trigger for IsSelected in a DataTemplate for ListBox items

<DataTemplate DataType="{x:Type vm:HeaderSlugViewModel}"> <vw:HeaderSlug...

4074
来自专栏魂祭心

原 canvas绘制clock

4304

扫码关注云+社区