1.什么是哈希

哈希也叫散列,因而哈希表也叫散列表。通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做哈希函数。采用散列函数将记录存储在一块连续的存储空间中,这块连续的存储空间称为哈希表。所得的存储地址称为哈希地址。

2.哈希的常见构造方法

2.1.直接定址

取关键字的某个线性函数为散列地址。即H(key)=key或者H(key)=a*key+b(a,b为常数)。
假设有数组[‘A’,‘B’,‘D’,‘F’,‘D’,‘E’,‘F’,‘C’],求该字符数组里每个字符的出现次数。利用ASCII码,哈希函数可以通过直接定址法H(key)=key-‘A’(ASCII码65),这样每一个key都可以将它的H(key)值,将其当成数组下标放在一个长度为26的int数组中。array[0]表示字母A出现的次数,array[1]表示字母B出现的次数。

2.2.数字分析

处理关键字位数比较多、数字出现频率不高的情况,通过抽取关键字的一部分进行操作,计算哈希存储位置。
假设在记录员工的生日,如20000618。若直接把年月日作为哈希地址,空间浪费很大,若是将月日作为哈希地址,则既能减少空间浪费又能降低哈希冲突的可能性。

2.3.平方取中

当无法确定关键字中哪几位分布较均匀时,可以求关键字的平方值,然后取平方值的中间几位作为散列地址。

2.4.除留取余

最常用的构造哈希函数方法。哈希函数为:
H(key) = key mod p
其中mod为取余运算,p<m,m为哈希表表长。
此方法不仅可以对关键字直接取模,也可以在折叠、平方取中之后再取模。

2.5.折叠法

适用于关键字位数很多,而且关键字每一位上数字分布大致均匀的情况。将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后去这几部分的叠加和舍去进位后作为散列地址。
假设关键字1472580369,表长为3。可将关键字分成4部分,147|258|036|9,147+258+036+9=450,取450为散列地址。

2.6.随机数

选择一个随机数,取关键字的随机函数值作为他的哈希地址。用于关键字长度不同的场合。哈希函数为:
H(key) = random (key)
其中random是随机函数。

2.7.如何选择

一般我们在考虑选择哪种哈希函数时,会考虑以下几点:

  • 计算哈希地址所需时间
  • 关键字长度
  • 哈希表大小
  • 关键字分布情况
  • 查找频率
    以上方法可以杂糅在一起使用。当然也可以扩展出其他的哈希函数。

3.哈希冲突

不同数据的关键字通过哈希函数得到一个相同的地址,这时就发生冲突,这种冲突一般叫做哈希冲突。把冲突的关键字称为这个哈希函数的同义词。
解决办法常见的有4种:开放地址法、再哈希法、链地址法、公共区溢出法。

3.1.开放地址法-线性探测

一旦发生冲突,就寻找下一个空的哈希地址,只要哈希表足够大,总能找到地址存放。

3.2.开放地址法-二次探测

在线性探测的基础上,多了寻找上一个空的哈希地址的办法。

3.3.开放地址法-随机探测

随机寻找一个空的哈希地址。

3.4.再哈希法

顾名思义,遇到哈希冲突时,换一个哈希函数计算。

3.5.链地址法

将同义词存储在一个单链表中,我们称这种单链表为同义词子表,哈希表中存储同义词子表的头指针。下图中的哈希函数为
H(key) = key mod 13。可以看出1、14、27、79取余结果都是1,哈希表中的地址1保存了1、14、27、79这个链表的头指针。

3.6.公共区溢出法

建立公共区,把哈希冲突的没有存储的同义词集中保留起来。

4.哈希表的优缺点

优点:不论哈希表中有多少数据,插入和删除很快,时间复杂度O(1);查询速度比数快,树的时间复杂度为O(n),因而若不需要有序遍历且数据量大小可预判,哈希表查询很快。
缺点:基于数组的数据结构,难于扩展。因而需要对表中数据量有清楚的认识。

5.哈希函数的使用场景

5.1.负载均衡

根据后端节点的某个固定属性(如来源 ip 、cookie、用户名等)计算哈希值,然后把所有节点计算出来的哈希值组成一个圆环。 请求过来时根据请求的特征计算该特征的哈希值, 然后顺时针查找哈希环上的哈希值,第一个比请求特征的哈希值大的哈希值所对应的节点即为被选中的节点。

5.2.安全加密

常见的加密算法都是哈希函数的实现:MD5、SHA、DES、AES。

5.3.唯一标识

任何文件在计算中都可以表示成二进制串。我们若是想要比对两个文件相等,可以给每个图片取一个唯一标识(信息摘要)。通过哈希函数得到一个哈希值,用它作为图片的唯一标识。用唯一标识来判定图片是否在图库中。

5.4.数据校验

在P2P下载协议中,我们会从不同的机器上下载同一部电影的不同部分,然后在自己的机器上将电影组装起来。如何知道这其中某个部分的电影下载过程中出了错误或者内容被篡改?先对所有部分进行哈希计算,并保存在种子文件中。等到所有部分下载完成,我们对所有部分进行哈希计算得到哈希值,再和种子文件中的进行比较,以此来校验文件是否完整。

5.5.数据分片

处理海量数据的时候,单台服务器无法加载和计算如此海量的数据,需要将海量数据均匀地分给n台服务器进行并行计算。可以使用除留取余哈希函数,对服务器个数n取模,相同结果的数据会被分到相同的服务器上,交给这台服务器处理。实现并行处理海量数据,最终再将结果合并起来。

5.6.分布式存储

为提高数据读、写能力,一般采用分布式存储,比如分布式缓存。因为大量数据要缓存,所以需要将数据分布在多机。原理同上面的数据分片。对机器个数n取模,就得到该缓存数据应存储的机器编号。
若是m个机器无法支撑,扩容到了m+n个机器,原来的哈希值都失效,需要重新计算,这将会导致穿透缓存直接请求数据库。
这时候可以使用一致性哈希函数。
假设我们有k个机器,数据的哈希值的范围是[0, MAX];将[0, MAX]划分为m个小区间(m远小于k),每个机器负责m/k个小区间。当新机器加入的时候,我们就将某个小区间的数据从原来的机器中搬移到新的机器中。这样,既不用全部重新哈希,也保持了各个机器上数据数量的均衡。
假设用户A的记录落在了D1机器,用户B的记录落在了D2机器,用户C的记录落在了D0机器上。哈希函数是H(key) = key mod 3。假设我们增加了一台机器,哈希函数需要变成H(key) = key mod 4。这就会出现用户明明存在记录但是却查不到的情况,如果重新哈希代价很大。那么一致性哈希是怎么做的呢?
一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,假设哈希函数的值空间为0到232-1。从0到232-1代表的分别是一个个的节点,这个环也叫哈希环。我们将我们的节点进行一次哈希,按照一定的规则,让节点落在哈希环上。

我们约定,通过数据key的哈希值落在哈希环上的节点,如果命中了机器节点就落在这个机器上,否则落在顺时针直到碰到第一个机器。A的哈希值落在了 D2 节点的前面,落在了D2机器上,D的哈希值在D1节点的前面,落在了D1机器上,B的哈希值刚好落在了D1节点上,其它依次类推。
当机器减少或增加的时候,假设D2因为一些原因宕机了,只有数据A的记录需要重新定位存储到节点D1上,其它的数据都没有被影响到;当我们需要增加一台机器D4,在D2和D1之间时,之前落在D2到D4之间的数据都需要重新定位到D4上面。

【数据结构】哈希(Hash)相关推荐

  1. Redis-04Redis数据结构--哈希hash

    文章目录 哈希概述 客户端操作hash Redis hash 结构命令 Spring操作reids的hash Step1 修改defaultSerializer Step2 操作hash 注意 代码 ...

  2. 【Redis】Redis 哈希 Hash 键值对集合操作 ( 哈希 Hash 键值对集合简介 | 查询操作 | 增加操作 | 修改操作 )

    文章目录 一.哈希 Hash 键值对集合 二.查询操作 1.Redis 中查询 Hash 键值对数据 2.查询 Hash 键是否存在 3.查询 Hash 中所有的键 Field 4.查询 Hash 中 ...

  3. Redis—列表(List)、集合(Set)、哈希(Hash)、有序集合 Zset

    Redis-列表List.集合Set.哈希Hash.有序集合 Zset 列表List 单键多值 常用命令 数据结构 Redis 集合(Set) 常用命令 数据结构 Redis 哈希(Hash) 常用命 ...

  4. Python中常用的数据结构---哈希表(字典)

    Python中常用的数据结构-哈希表(字典) 常用的数据结构有数组.链表(一对一).栈和队列.哈希表.树(一对多).图(多对多)等结构. 在本目录下我们将讲解,通过python语言实现常用的数据结构. ...

  5. 数据结构——哈希表的详解与实现

    数据结构--哈希表(HashTable) 1.前言 ​ 当我们频繁的查找数据中的某个元素时,我们通常会选择数组来存放数据,因为数组的的内存是连续的,可以直接通过下标访问数据,但是它添加和删除数据比较麻 ...

  6. Redis数据结构为字典Hash 实践 之 系统数据字典实时触发缓存存储

    一.项目用redis-learn,文章参考 Hash底层存储数据的方式确实跟其他数据结构有点不同,其他数据结构几乎都是:Key-Value的存储,而Hash则是:Key – [Field-Value] ...

  7. Redis数据结构为字典Hash 的 存储、获取、删除等的操作

    一.项目用redis-learn,文章参考 Hash底层存储数据的方式确实跟其他数据结构有点不同,其他数据结构几乎都是:Key-Value的存储,而Hash则是:Key – [Field-Value] ...

  8. 算法笔记(三)特殊数据结构——哈希表、有序表、并查集、KMP、Manacher、单调栈、位图、大数据类题

    layout: post title: 算法笔记(三)特殊数据结构--哈希表.有序表.并查集.KMP.Manacher.单调栈.位图.大数据类题 description: 算法笔记(三)特殊数据结构- ...

  9. java hashtable 数据结构_数据结构--哈希表(Java)

    数据结构--哈希表(Java) 介绍 哈希表 底层是 数组加链表 或者是 数组加二叉树 ,一个数组里面有多个链表,通过散列函数来提高效率 代码 package cn.guizimo.hashtab; ...

  10. Redis学习---(8)Redis 哈希(Hash)

    Redis 哈希(Hash) Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象. Redis 中每个 hash 可以存储 232 - 1 键值 ...

最新文章

  1. java web json_java web中对json的使用详解
  2. python的图表库_python 图表库
  3. ie6常见css bug
  4. 【C++】typename
  5. 2009年上半年网络工程师考试下午试卷参考答案(二)
  6. 漫步微积分二——微积分是什么
  7. Python中groupby的简单使用
  8. android tab pageview,Android Fragment在ViewPager中到底经历了什么?
  9. python 近期用到的基础知识汇总(主要是numpy和pytorch的相关矩阵变化函数)(一)
  10. Impala命令COMPUTE STATS的解析
  11. LaTeX简介及其在Mardown中的用法
  12. 故障树分析法MATLAB,基于VC++与MATLAB的故障树分析系统
  13. uc手机浏览器 手机模拟_移动端页面调试工具——UC浏览器开发者版
  14. SQLServer实现快速进行简繁体的翻译功能
  15. SparkStreaming + LogisticRegression 实现路况预测
  16. 几行烂代码,用错 Transactional,我赔了16万
  17. 蜗牛星际b款装服务器系统,蜗牛星际 B款 双网口 全新安装黑群晖
  18. JST :Joint sentiment topic model ASUM :Aspect sentiment unification model
  19. Linux设置虚拟内存
  20. 又一家著名游戏公司在西雅图开分店了

热门文章

  1. 南京理工大学计算机研究生复试面试
  2. python math 数学函数教程
  3. smith 图中Q值和阻抗匹配
  4. 基于C#.NET三层架构物流运输管理系统(TMS)-C/S框架网原创作品
  5. Tivoli Workload Scheduler (TWS)
  6. 高数笔记(十九):对面积的曲面积分,对坐标的曲面积分,高斯公式,斯托克斯公式
  7. 和周杰讨论:DB2连接问题
  8. Java实验报告误差分析怎么写_系统工程实验报告-031510131-郭文豪.doc
  9. 九位SEO专家分享他们对Google核心更新的看法
  10. Extraneous non-emits event listeners (onJump) were passed to component but could not be automaticall