初识hash

2023-05-16

1.哈希表

    哈希表(Hash Table)是一种根据关键字直接访问内存存储位置的数据结构。通过哈希表,数据元素的存放位置和数据元素的关键字之间建立起某种对应关系,建立这种对应关系的函数称为哈希函数,也可以叫做散列函数,存放记录的数组叫做散列表,h(x)为哈希函数。


2.基本概念

  • 若关键字为k,则其值存放在f(k)的存储位置上。由此,不需比较便可直接取得所查记录。称这个对应关系f为散列函数(Hash function),按这个思想建立的表为散列表
  • 对不同的关键字可能得到同一散列地址,即k1不等于k2,而f(k1)=f(k2),这种现象称碰撞(Collision)。如下图。

     具有相同函数值的关键字对该散列函数来说称做同义词。综上所述,根据散列函数Hash(k)和处理碰撞的方法将一组关键字映象到一个有限的连续的地址集(区间)上,并以  关键字在地址集中的“象”作为记录在表中的存储位置,这种表便称为散列表,这一映象过程称为散列造表散列,所得的存储位置称散列地址

  • 若对于关键字集合中的任一个关键字,经散列函数映象到地址集合中任何一个地址的概率是相等的,则称此类散列函数为均匀散列函数(Uniform Hash function),这就是使关键字经过散列函数得到一个“随机的地址”,从而减少碰撞。

3.构造散列函数

   散列函数能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快定位。哈希表的构造方法是:假设要存储的数据元素个数为n,设置一个长度为m(m≥n)的连续存储单元,分别以每个数据元素的关键字为自变量,通过哈希函数,把映射为内存单元的某个地址,并将该数据元素存储在该内存单元中。

从数学的角度来看,哈希函数实际上是关键字到内存单元的映射,因此我们希望通过哈希函数通过尽量简单的运算使得通过哈希函数计算出的哈希地址尽 量均匀地被映射到一系列的内存单元中。构造哈希函数有三个要点:第一,运算过程要尽量简单高效,以提高哈希表的插入和检索效率;第二,哈希函数应该具有较好的散列性,以降低哈希冲突的概率;第三,哈希函数应具有较大的压缩性,以节省内存。

  1. 直接寻址法:取关键字或关键字的某个线性函数值为散列地址。即hash(k)=k或hash(k)=a*k+b,其中a,b为常数(这种散列函数叫做自身函数)优点是不会产生冲突,但缺点空间复杂度可能会很高,适用于元素较少的情况下
  2. 数字分析法:假设关键字是以r为基的数,并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。
  3. 平方取中法:取关键字平方后的中间几位为哈希地址。通常在选定哈希函数时不一定能知道关键字的全部情况,取其中的哪几位也不一定合适,而一个数平方后的中间几位数和数的每一位都相关,由此使随机分布的关键字得到的哈希地址也是随机的。取的位数由表长决定。
  4. 折叠法:将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。
  5. 随机数法: H(key)=random(key) ,其中random为随机函数。通常用于关键字长度不等时采用此法
  6. 除留余数法:取关键字被某个不大于散列表表长C的数K除后所得的余数为散列地址。该方法计算简单,适用范围广,是最经常使用的一种哈希函数,可以表示为:,该方法的关键是常数的选取,一般取素数,若p选择不好,容易产生碰撞一般要求是接近或等于哈希表本身的长度,理论研究表明,该常数取素数时效果最好。

4.处理碰撞

 在构造哈希表时,存在这样的问题,对于两个不同的关键字,通过我们的哈希函数计算哈希地址时却得到了相同的哈希地址,我们将这种现象称为哈希冲突.

  哈希冲突主要与两个因素相关:第一,填装因子,所谓的填装因子是指哈希表中已存入的数据元素个数n与哈希地址空间大小的m比值,即α=n/m,α越 小,冲突的可能性就越小,相反则冲突可能性越大;但是α越小,哈希表的存储空间利用率也就很低,α越大,存储空间的利用率也就越高,为了兼顾哈希冲突和存 储空间利用率,通常将α控制在0.6-0.9之间,而.NET中的Hashtable则直接将α的最大值定义为0.72(注:虽然微软官方MSDN中声明 Hashtable默认填装因子为1.0,事实上所有的填装因子都为0.72的倍数);第二,与所用的哈希函数有关,如果哈希函数选择得当,就可以使哈希地址尽可能的均匀分布在哈希地址空间上,从而减少冲突的产生,但一个良好的哈希函数的得来很大程度上取决于大量的实践,不过幸好前人已经总结实践了很多高 效的哈希函数,可以参考园子里大牛Lucifer的文章:数据结构 : Hash Table [I]。

哈希冲突通常是很难避免的,解决哈希冲突有很多种方法,通常分为两大类:

4.1开放定址法

   它是一类以发生哈希冲突的哈希地址为自变量,通过某种哈希函数得到一个新的空闲内存单元地址的方法(如图),开放定址法的哈希冲突函数通常是一组;


4.1.1线性探查法(Linear Probing)

该方法的基本思想是:将散列表T[0..m-1]看成是一个循环向量,若初始探查的地址为d(即 h(key)=d),则最长的探查序列为:d,d+l,d+2,…,m-1,0,1,…,d-1 .即:探查时从地址d开始,首先探查T[d],然后依次探查T[d+1],…,直到T[m-1],此后又循环到T[0],T[1],…,直到探查到 T[d-1]为止。探查过程终止于三种情况:

(1)若当前探查的单元为空,则表示查找失败(若是插入则将key写入其中);

(2)若当前探查的单元中含有key,则查找成功,但对于插入意味着失败;

(3)若探查到T[d-1]时仍未发现空单元也未找到key,则无论是查找还是插入均意味着失败(此时表满)。

利用开放地址法的一般形式,线性探查法的探查序列为:

hi =(h(key)+i)%m0≤i≤m-1 //即di =i

hi=(h(key)+di) mod mi=1,2,...,k(k<=m-1)

其中m为表长,di为增量序列

如果di值可能为1,2,3,...m-1,称线性探测再散列。

如果di取值可能为1,-1,2,-2,4,-4,9,-9,16,-16,...k*k,-k*k(k<=m/2)

称二次探测再散列。

如果di取值可能为伪随机数列。称伪随机探测再散列。开放地址法堆装填因子的要求

开放定址法要求散列表的装填因子α≤l,实用中取α为0.5到0.9之间的某个值为宜。


4.1.2二次探查法(quadratic probing)

二次探查法的探查序列是:

hi=(h(key)+i*i)%m0≤i≤m-1 //即di=i^2

即探查序列为d=h(key),d+1^2,d+2^2,d+3^2…

该方法的缺陷是不易探查到整个散列空间。

4.1.3双重散列法(double hashing)

该方法是开放定址法中最好的方法之一,它的探查序列是:

hi=(h(key)+i*h1(key))%m0≤i≤m-1 //即di=i*h1(key)

即探查序列为:

d=h(key),(d+h1(key))%m,(d+2h1(key))%m,…,等。

该方法使用了两个散列函数h(key)和h1(key),故也称为双散列函数探查法。

 

4.2链表法

   当未发生冲突时,则直接存放该数据元素;当冲突产生时,把产生冲突的数据元素另外存放在单链表中。


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

 

链地址法处理冲突时的Hash表

4.3再哈希法

  均是不同的哈希函数,即在同一词产生地址冲突时计算另一个哈希函数地址,直到冲突不再发生。这种方法不易产生“聚集”,但是增加了计算的时间。

4.4.建立公共溢出区公共溢出区

   假设哈希函数的值域为[0,m-1],则设向量hashtable[0..m-1]为基本表,另外设立存储空间向量overtable[0..v]用以存储发生冲突的记录。

性能分析

插入和删除的时间均取决于查找,故下面只分析查找操作的时间性能。

虽然散列表在关键字和存储位置之间建立了对应关系,理想情况是无须关键字的比较就可找到待查关键字。但是由于冲突的存在,散列表的查找过程仍是一个和关键字比较的过程,不过散列表的平均查找长度比顺序查找、二分查找等完全依赖于关键字比较的查找要小得多。

(1)查找成功的asl

散列表上的查找优于顺序查找和二分查找。

(2) 查找不成功的asl

对于不成功的查找,顺序查找和二分查找所需进行的关键字比较次数仅取决于表长,而散列查找所需进行的关键字比较次数和待查结点有关。因此,在等概率情况下,也可将散列表在查找不成功时的平均查找长度,定义为查找不成功时对关键字需要执行的平均比较次数。

注意

①由同一个散列函数、不同的解决冲突方法构造的散列表,其平均查找长度是不相同的。

②散列表的平均查找长度不是结点个数n的函数,而是装填因子α的函数。因此在设计散列表时可选择α以控制散列表的平均查找长度。

③ α的取值

   α越小,产生冲突的机会就小,但α过小,空间的浪费就过多。只要α选择合适,散列表上的平均查找长度就是一个常数,即散列表上查找的平均时间为o(1)。

④ 散列法与其他查找方法的区别

除散列法外,其他查找方法有共同特征为:均是建立在比较关键字的基础上。其中顺序查找是对无序集合的查找,每次关键字的比较结果为"="或"!="两种可能,其平均时间为o(n);其余的查找均是对有序集合的查找,每次关键字的比较有"="、"<"和"& gt;"三种可能,且每次比较后均能缩小下次的查找范围,故查找速度更快,其平均时间为o(lgn)。而散列法是根据关键字直接求出地址的查找方法,其查 找的期望时间为o(1)。

例子:选取哈希函数h(k)=(3k)%11,用线性探测再散列法处理冲突。

试在0~10的散列地址空间中,对关键序列22,41,53,46,30,13,01,67构造哈希表,并求等概率情况下查找不成功的平均查找长度asl。







本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

初识hash 的相关文章

  • rspec - 为什么仅在 ubuntu 上,当它们相同时,使用 assert_equal 进行此属性比较会失败?

    两个测试都失败了 但仅在 Ubuntu 12 上失败 但在我的 新 Mac 上却失败了 失败的两个是 Active Record 对象属性比较 但我尽了最大努力来比较它们 例如在命令行创建哈希并粘贴属性 比较表明它们是相同的 这是一个真正的
  • 按月和年将日期的 Ruby 数组分组为哈希

    假设我有一个 Ruby 数组Dates like 2011 01 20 2011 01 23 2011 02 01 2011 02 15 2011 03 21 创建按年和按月对日期元素进行分组的哈希的简单且 Ruby 式的方法是什么 例如
  • Ruby 数组上未定义的方法“to_h”

    As per Ruby 数组文档 http ruby doc org core 2 2 0 Array html method i to h 有一个方法to h只要数组的每个元素是另一个包含两个元素的数组 就可以使用它将数组转换为哈希 以下
  • Perl 中大型哈希表的快速加载

    我有大约 30 个文本文件 其结构如下 wordleft1 wordright1 wordleft2 wordright2 wordleft3 wordright3 文件总大小约1GB 包含约3200万行单词组合 我尝试了几种方法来尽可能快
  • 什么整数哈希函数可以接受整数哈希键?

    什么整数哈希函数可以接受整数哈希键 我发现以下算法提供了非常好的统计分布 每个输入位以大约 50 的概率影响每个输出位 不存在冲突 每个输入都会产生不同的输出 除非 CPU 没有内置整数乘法单元 否则该算法速度很快 C 代码 假设int是
  • C# 如何计算出对象的哈希码?

    这个问题来自于讨论tuples https stackoverflow com questions 101825 whats the best way of using a pair triple etc of values as one
  • set 中的哈希表在 python 中如何工作?

    据我所知 set在python中通过哈希表来实现O 1 查找复杂度 虽然它是哈希表 但其中的每个条目set必须是可散列的 或不可变的 所以这种和平的代码引发了异常 gt gt gt dict Traceback most recent ca
  • 哈希链接重新加载页面

    我有一个安装在第三方网站上的代码片段 我无法了解详细信息 但它通过使用 a 将 HTML CSS 和 JS 加载到页面上
  • MacOS X 上使用 crypt 进行 Python SHA512 加盐密码

    我正在尝试生成加密的密码字符串 类似于Linux中的 etc shadow 由于某种原因 我得到的输出是不同的 我有什么想法吗 一个比另一个长 不包括盐部分 usr bin python import crypt alg 6 SHA512
  • 使用哈希检查具有 $_POST 值的页面是否已刷新

    当将表单发布到同一个PHP页面时 正确的方法是什么来查找页面是否被意外刷新而不是再次提交 这是我现在正在使用的 tmp implode POST myHash md5 tmp if isset SESSION myHash SESSION
  • Oh-my-zsh 哈希(井号)符号错误模式或未找到匹配项

    我很确定是与我的 Oh my zsh 配置相关的东西 但我不知道它是什么 当我在 git 命令中使用 符号时 但也适用于其他所有命令 例如 ls 2 我收到 错误模式 错误或 找不到匹配项 我猜是要计算一些东西 但我找不到在哪里配置它 I
  • 使用javascript向url添加哈希而不滚动页面?

    在不滚动页面的情况下向 url 添加哈希 使用 JavaScript 我打开页面 我向下滚动 我单击添加哈希的链接 可能带有值 test 示例 http www example com test http www example com t
  • Rails 4 - 将地址保存为数据库中的一列

    我是 Rails 新手 正在开发一个简单的应用程序 我的 ERD 中有一个名为 Client 的模型 并且希望保存每个客户的地址 我最初的想法是将地址保存为单独的字段 即 rails g model Client address first
  • 将 Python 中的 SHA 哈希计算转换为 C#

    有人可以帮我将以下两行 python 代码转换为 C 代码吗 hash hmac new secret data digestmod hashlib sha1 key hash hexdigest 8 如果您有兴趣 其余的看起来像这样 us
  • 防止 .exe 时间戳发生变化

    有谁知道如何防止可执行文件的时间戳更改 我正在尝试为 exe 生成一致的哈希代码 但我认为时间戳可能会阻止这种情况发生 每次我重新编译代码 VS C 时 FastSum 都会生成不同的校验和 Thanks PE 文件格式 如 EXE 中 具
  • 为什么即使我的哈希码值相同,“==”也会返回 false

    我写了一个像这样的课程 public class HashCodeImpl public int hashCode return 1 public static void main String args TODO Auto generat
  • 数学组合的完美最小哈希

    首先定义两个整数N and K where N gt K 两者都在编译时已知 例如 N 8 and K 3 接下来 定义一组整数 0 N or 1 N 如果这使答案更简单 并调用它S 例如 0 1 2 3 4 5 6 7 的子集数量S wi
  • 在 Perl 中使用数据引用的正确方法

    我有一组想要处理的数据 为了简化我的代码 最好通过指向原始数据的引用数组来访问我的数据的某些子集 比解释更好的是 我写下了这个例子 它还没有工作 最后 我想更新原始数据 而不必更新所有子集 用 Perl 可以做这样的事情吗 usr bin
  • 如何使用“子例程引用”作为哈希键

    在 Perl 中 我正在学习如何取消引用 子例程引用 但我似乎无法使用子例程引用作为哈希 键 在下面的示例代码中 我可以创建对子例程 subref 的引用 然后取消引用它以运行子例程 subref 我可以使用引用作为哈希 值 然后轻松取消引
  • 根据哈希值确认文件内容

    我需要 检查完整性 content文件数量 文件将写入 CD DVD 可能会被复制多次 这个想法是识别正确复制的副本 在从 Nero 等中删除它们之后 我对此很陌生 但快速搜索表明Arrays hashCode byte http down

随机推荐

  • Redis穿透、雪崩、击穿以及在生产环境中的解决办法

    Redis穿透 雪崩 击穿以及在生产中的解决办法 redis 经典八股文 xff0c 以及生产中的应对方式 一 缓存穿透 redis缓存和数据库中都没有相关数据的情况下 xff0c 由于redis中没有相关的数据 xff0c 无法拦截 xf
  • 地点主机号的最大值和最小值

    某单位分配到一个B类IP地址 xff0c 其网络号为129 250 0 0 该单位有4000台机器 xff0c 平均分布16个不同的地点 如选用子网掩码255 255 255 0 试给每一个地点分配一个子网号码 xff0c 并算出每个地点主
  • cas单点登录-自定义登录界面 / 自定义主题风格(三)

    cas单点登录 自定义登录界面 自定义主题风格 xff08 三 xff09 在前面的文章中 xff0c 介绍了使用cas实现SSO单点登录 xff0c 静态登录 xff0c 使用mysql数据库登录 但是在登录时都是跳转到了同一个登录界面
  • 切片地图服务器

    地图服务 收集了一些切片地图的URL xff0c 以后慢慢完善 天地图提供四种类型的地图 1 天地图地形 http t span class hljs list 0 7 span tianditu com DataServer T 61 t
  • Linux应用程序开发笔记:nanopi-m4(rk3399)opencv

    参考资料 xff1a OpenCV中文网站 OpenCV官网手册 图像处理 xff1a opencv的目标追踪方法总结 qt利用opencv3 4进行人脸识别和特征点提取 基于OpenCV下 多红外目标检测 跟踪 质心坐标提取 跟踪目标排序
  • samba服务免密码访问配置一

    A 安装前的准备工作 xff1a SELINUX 61 disabled 关闭防火墙 xff1a service iptables stop B 执行如下命令安装samba xff1a root 64 samba yum install s
  • androidmediacodec强制申请关键帧

    https github com AnyRTC anyRTC RTMP OpenSource issues 49 V H264Encoder RequestKeyFrame Android 6 0推送全是I 帧 或者全是P帧 急急急 49
  • C#的Convert 类使用

    C 的Convert 类使用 一 从基类型转换 二 Convert 类的常用方法说明 2 1 ChangeType Object Type 2 2 GetTypeCode Object 2 3 Convert ToByte 2 4 Conv
  • XTDrone简明安装教程

    XTDrone简明安装教程 XTDrone是基于PX4 ROS与Gazebo的无人机通用仿真平台 支持多旋翼飞行器 xff08 包含四轴和六轴 xff09 固定翼飞行器 复合翼飞行器 xff08 包含quadplane xff0c tail
  • 我的算法学习之路

    xfeff xfeff xfeff 关于 严格来说 xff0c 本文题目应该是我的数据结构和算法学习之路 xff0c 但这个写法实在太绕口 况且CS中的算法往往暗指数据结构和算法 xff08 例如算法导论指的实际上是数据结构和算法导论 xf
  • 个人面试经验分享

    九月 十月是收获的季节 xff0c 也是奔波的季节 我也不例外 xff0c 没有特殊的机遇 xff0c 也是经历了一次残酷的海选啊 xff0c 把我经历简单的分享给各位学弟学妹们 我数了一下大概面了六家公司 xff1a 阿里 xff0c 华
  • ImageField用法的一个例子

    本文以注册头像为例讲解一下ImageField怎么用 第1步我们要定义一个ImageField 在models py里面定义 这个是用来写到数据库里面的 def custom path instance filename ext 61 fi
  • ubuntu20.04配置远程连接sshd服务

    ubuntu20 04配置远程连接sshd服务 1 为什么要配置 xff1f 两种可能 xff1a 本机虚拟机上安装的系统 这种情况就是为了方便 xff0c 因为在虚拟机上只能操作不是很方便 xff01 远程机房的服务器 这种是必须的 xf
  • 使用adb从手机拉取apk包

    1 找到app对应的包名 xff1a 2 3 1 adb shell am monitor 2 启动需要获取包名的应用 3 窗口就会打印出来当前应用的包名 或者 xff1a 查看手机上所有app包名 xff1a adb shell pm l
  • 使用c++filt工具demangle C++符号

    demangle符号名 在调试C 43 43 程序时 经常会遇到未demangle的C 43 43 符号名 不了解mangle的规则时 并不太容易确定具体是哪个API 比如 使用objdump将boost日志动态库的符号表导出 你是否能够很
  • 我的2014

    不知不觉中2014已经离我们远去了 xff0c 回想起2014 xff0c 我经历了太多 xff0c 又不知从何说起 2013年年末我开通了CSDN博客 xff0c 所以我真正开始写博客是在2014年1月份 xff0c 在2014年中写博客
  • Zsh 入门(安装及使用)

    Zsh 入门 本文前提 CentOS 6 7 64 bitroot 用户 Zsh 介绍 Zsh 兼容 Bash xff0c 据传说 99 的 Bash 操作 和 Zsh 是相同的Zsh 官网 xff1a http www zsh org 先
  • 炼丹笔记二:数据清洗问题

    欢迎大家关注微信公众号 xff1a baihuaML xff0c 白话机器学习 码字不易 xff0c 未经授权禁止转载 xff0c 如转载 xff0c 请添加知乎好友 xff1a 会写代码的好厨师 xff0c 私信我 xff01 在这里 x
  • LayoutLM——文本与布局的预训练用于文档图像理解

    摘要 xff1a 预训练技术近年来在多种NPL任务中取得了广泛的成功 尽管广泛的NPL应用的预训练模型 xff0c 其大多聚焦于文本级别的操作 xff0c 而忽略了布局与风格信息 xff0c 这对文档图像的理解至关重要 该篇论文提出了Lay
  • 初识hash

    1 哈希表 哈希表 xff08 Hash Table xff09 是一种根据关键字直接访问内存存储位置的数据结构 通过哈希表 xff0c 数据元素的存放位置和数据元素的关键字之间建立起某种对应关系 xff0c 建立这种对应关系的函数称为哈希