哈希是什么

引入:我们在学习数组的时候,使用数组元素的下标值即可访问到该元素,所花费的时间是O(1),与数组元素的个数n没有关系,这就是哈希方法的核心思想。

哈希方法:以关键值K为自变量,通过一定的函数关系h(K)(哈希函数)计算出对应的函数值,把这个值解释为结点的存储地址,将结点的关键码(key)和属性数据(value)一起存入此存储单元中。检索时,用同样的函数计算出地址,找到对应的数据。

哈希表:按哈希存储方式构造的存储结构称为哈希表(hash table)

举例:已知线性表关键码值集合为S={and, begin, do, else, for,golang},假设哈希函数是关键码K的第一个字母在字母表中的序号,哪么可以建立如下的哈希表:

当然这个例子特别简单,细心的同学很快就发现了二个问题:

  1. 如果S中有类似于and,apple这样的关键码,哪么这个表还怎么存放,在1的位置存放and还是apple呢?(这种现象称为冲突)
  2. 分配的空间大小比实际所需的要大一点(一般情况下,哈希表的空间(H)比结点的集合(M)大,这样虽然浪费了空间,但是换来了检索效率,称α=M/H为哈希表的负载因子)

其实这就是接下来要谈到的哈希函数的选择和冲突解决策略。

哈希函数

哈希方法的核心就是哈希函数的选择,理想的哈希函数应该使得结点“分布均匀”,且冲突少

为了简单起见,以下的哈希函数我们假设关键值都是整数(如果不是整数,哪也有特定的方法可以把它转换为整数,毕竟在计算机世界里,任何东西都是01组成的串)

除余法:

关键值码k除以M(往往取哈希表的长度),并取余数作为哈希地址。

乘余取整法

先让关键码k乘上一个常数A(0<A<1),提取乘积的小数部分。然后,再用整数n乘以这个值,对结果向下取整,将其作为哈希的地址。

有许多种哈希函数可以选择,每种都有其适用的场景,但是作为软件开发工程师,我们只要理解它的思想就可以,至于什么场景选择什么哈希函数,哪大概率是数学家应该研究的问题。

优秀的哈希函数可以尽可能的避免产生冲突,但是冲突的产生是不可避免地,这就是接下来要谈到的冲突解决策略

冲突解决策略

冲突解决技术可以分为两类,拉链法和开地址法,这两种方法的不同之处在于,拉链法把发生冲突的关键码存储在哈希表主表之外,而开地址法把发生冲突的关键码存储在表中另一个槽内。

拉链法

拉链法的一种简单形式是把哈希表中的每一个槽定义为一个链表的表头,哈希到一个特定槽的所有记录都放到这个槽的链表中。

假设S={and, apple, begin, do, dog, else, for, go, golang},哈希函数还是关键码K的第一个字母在字母表中的序号。哪么可以建立如下的哈希表:

开地址法

开地址法把所有记录直接存储在哈希表中。每个记录关键码K有一个由哈希函数计算出来的基位置,即h(k)。如果要插入一个关键码k,而另一个记录的关键码已经占据了k的基位置(发生冲突)则把k存储在表中的其他地址内,至于其他地址怎么选择,有多种算法,我们以顺序探测法为例。

已知一组关键码为{26,36,41,38,44,15,68,12,06,51,25},哈希表长度L=15,用线性探查法解决冲突构造的哈希表的过程如下:

利用除余数作为哈希函数,假设选择M=13,则散列函数为:h(k)=k%13,按顺序插入各个结点:

h(26)=0, h(36)=10,h(41)=2, h(38)=12, h(44)=5,

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
26 25 41 44 36 38

h(15)=0,发生碰撞,因此需要进行探查,按照顺序探测法,显然3为开放的空闲地址,因此可以将其放在3单元。

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
26 25 41 15 44 36 38

68和12也类似,最后的哈希表如下所示:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
26 25 41 15 68 44 6 36 38 12 51

小结

本文简述了哈希表的基本概念和思想,作为软件工程师,掌握这些知识足够我们从事工程开发了,至于一些偏数学方面的知识,比如散列方法的效率分析,以及相关的一些优化,本文就不再讲述。

参考资料:《数据结构与算法》张铭 编著

哈希表(hash table)基础概念的更多相关文章

  1. 算法与数据结构基础 - 哈希表(Hash Table)

    Hash Table基础 哈希表(Hash Table)是常用的数据结构,其运用哈希函数(hash function)实现映射,内部使用开放定址.拉链法等方式解决哈希冲突,使得读写时间复杂度平均为O( ...

  2. PHP关联数组和哈希表(hash table) 未指定

    PHP有数据的一个非常重要的一类,就是关联数组.又称为哈希表(hash table),是一种很好用的数据结构. 在程序中.我们可能会遇到须要消重的问题,举一个最简单的模型: 有一份username列表 ...

  3. 什么叫哈希表(Hash Table)

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

  4. 词典(二) 哈希表(Hash table)

    散列表(hashtable)是一种高效的词典结构,可以在期望的常数时间内实现对词典的所有接口的操作.散列完全摒弃了关键码有序的条件,所以可以突破CBA式算法的复杂度界限. 散列表 逻辑上,有一系列可以 ...

  5. 数据结构 哈希表(Hash Table)_哈希概述

    哈希表支持一种最有效的检索方法:散列. 从根来上说,一个哈希表包含一个数组,通过特殊的索引值(键)来访问数组中的元素. 哈希表的主要思想是通过一个哈希函数,在所有可能的键与槽位之间建立一张映射表.哈希 ...

  6. 哈希表(Hash table)

  7. Redis原理再学习04:数据结构-哈希表hash表(dict字典)

    哈希函数简介 哈希函数(hash function),又叫散列函数,哈希算法.散列函数把数据"压缩"成摘要,有的也叫"指纹",它使数据量变小且数据格式大小也固定 ...

  8. Hash表 hash table 又名散列表

    直接进去主题好了. 什么是哈希表? 哈希表(Hash table,也叫散列表),是根据key而直接进行访问的数据结构.也就是说,它通过把key映射到表中一个位置来访问记录,以加快查找的速度.这个映射函 ...

  9. 哈希表(Hash)的应用

    $hs=@() #定义数组 $hs=@{} #定义Hash表,使用哈希表的键可以直接访问对应的值,如 $hs["王五"] 或者 $hs.王五 的值为 75 $hs=@''@ #定义 ...

  10. (四)Redis哈希表Hash操作

    Hash全部命令如下: hset key field value # 将哈希表key中的字段field的值设为value hget key field # 返回哈希表key中的字段field的值val ...

随机推荐

  1. NodeJs 的Module.export 和 export

    NodeJs  的Module.export 和 export 是一样的. 但是Module.export ={....} 可以起效,.export ={....} 是失效的. 这里的export  ...

  2. 货币转换B

    描述 人民币和美元是世界上通用的两种货币之一,写一个程序进行货币间币值转换,其中:‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮ ...

  3. SpringBoot mysql出现The server time zone value '�й���׼ʱ��' is unrecogni

    MySql :8.0.18 引入的mysql驱动: SpringBoot整合Mybatis的框架,在访问Controller的时候 : ava.sql.SQLException: The server ...

  4. 【Distributed】分布式配置中心

    一.概述 1.1 什么是分布式配置中心 常用分布式配置中心框架 二.Apollo阿波罗 2.1 Apollo特点 2.2 Apollo整体架构原理 2.3 Apollo Portol 环境搭建 Lin ...

  5. Ceph 调整crush map

    目录 Ceph 调整crush map 1.前言 2.示例 1.创建新的replicated 2.修改当前pool的rule Ceph 调整crush map 1.前言 本文章适用于ceph n版 2 ...

  6. 一分钟了解Linux文件系统

    Linux文件系统原理在所有的操作系统中文件都有文件名与数据,在Linux系统上文件系统分成两个部分:用户数据 (user data) 与元数据 (metadata).用户数据,即文件数据块 (dat ...

  7. haproxy??

    HAProxy是一个使用C语言编写的自由及开放源代码软件,其提供高可用性.负载均衡,以及基于TCP和HTTP的应用程序代理. HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保 ...

  8. Linux shell批量执行scp脚本工具

    转载: linux shell + expect:批量scp脚本工具             2011-09-13 15:51:06 分类: Python/Ruby 最近在准备一个部署的任务,其中有一 ...

  9. 通过字节码分析this关键字以及异常表的重要作用

    在之前的字节码分析中缺少对异常的介绍,这次主要来对字节码异常表相关的东东进行一个学习,下面先来编写一个相关异常的小程序: 接着编译来看用javap -verbose来查看一下它的字节码信息: xion ...

  10. java 基础:方法调用中的值传递是call by value,并且传递的是参数的值的拷贝,而不是引用

    public class TestExtends { public static void main(String[]args){ int s = 10; System.out.println(Sys ...