精华内容
下载资源
问答
  • 几种常见的哈希函数(散列函数)构造方法 直接定址法 取关键字或关键字的某个线性函数值为散列地址。 即 H(key) = key 或 H(key) = a*key + b,其中a和b为常数。 比如 除留余数法 取关键字被某个不大于散...

    几种常见的哈希函数(散列函数)构造方法

    • 直接定址法 
      • 取关键字或关键字的某个线性函数值为散列地址。
      • 即 H(key) = key 或 H(key) = a*key + b,其中a和b为常数。
      • 比如这里写图片描述
    • 除留余数法 
      • 取关键字被某个不大于散列表长度 m 的数 p 求余,得到的作为散列地址。
      • 即 H(key) = key % p, p < m。 
      • 比如这里写图片描述
    • 数字分析法 
      • 当关键字的位数大于地址的位数,对关键字的各位分布进行分析,选出分布均匀的任意几位作为散列地址。
      • 仅适用于所有关键字都已知的情况下,根据实际应用确定要选取的部分,尽量避免发生冲突。
      • 比如 这里写图片描述
    • 平方取中法 
      • 先计算出关键字值的平方,然后取平方值中间几位作为散列地址。
      • 随机分布的关键字,得到的散列地址也是随机分布的。
      • 比如 这里写图片描述
    • 折叠法(叠加法) 
      • 将关键字分为位数相同的几部分,然后取这几部分的叠加和(舍去进位)作为散列地址。
      • 用于关键字位数较多,并且关键字中每一位上数字分布大致均匀。 
      • 比如 这里写图片描述
    • 随机数法 
      • 选择一个随机函数,把关键字的随机函数值作为它的哈希值。
      • 通常当关键字的长度不等时用这种方法。 

    构造哈希函数的方法很多,实际工作中要根据不同的情况选择合适的方法,总的原则是尽可能少的产生冲突。

    通常考虑的因素有关键字的长度和分布情况、哈希值的范围等。

    如:当关键字是整数类型时就可以用除留余数法;如果关键字是小数类型,选择随机数法会比较好。

    哈希冲突的解决

    选用哈希函数计算哈希值时,可能不同的 key 会得到相同的结果,一个地址怎么存放多个数据呢?这就是冲突。

    常用的主要有两种方法解决冲突:

    1.链接法(拉链法)

    拉链法解决冲突的做法是: 
    将所有关键字为同义词的结点链接在同一个单链表中。

    若选定的散列表长度为 m,则可将散列表定义为一个由 m 个头指针组成的指针数组 T[0..m-1] 。

    凡是散列地址为 i 的结点,均插入到以 T[i] 为头指针的单链表中。 
    T 中各分量的初值均应为空指针。

    在拉链法中,装填因子 α 可以大于 1,但一般均取 α ≤ 1。

    这里写图片描述

    2.开放定址法

    用开放定址法解决冲突的做法是:

    用开放定址法解决冲突的做法是:当冲突发生时,使用某种探测技术在散列表中形成一个探测序列。沿此序列逐个单元地查找,直到找到给定的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。查找时探测到开放的地址则表明表中无待查的关键字,即查找失败。

    简单的说:当冲突发生时,使用某种探查(亦称探测)技术在散列表中寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到。

    按照形成探查序列的方法不同,可将开放定址法区分为线性探查法、二次探查法、双重散列法等。

    a.线性探查法

    hi=(h(key)+i) % m ,0 ≤ i ≤ m-1 

    基本思想是: 
    探查时从地址 d 开始,首先探查 T[d],然后依次探查 T[d+1],…,直到 T[m-1],此后又循环到 T[0],T[1],…,直到探查到 有空余地址 或者到 T[d-1]为止。

    b.二次探查法

    hi=(h(key)+i*i) % m,0 ≤ i ≤ m-1 

    基本思想是: 
    探查时从地址 d 开始,首先探查 T[d],然后依次探查 T[d+1^2],T[d+2^2],T[d+3^2],…,等,直到探查到 有空余地址 或者到 T[d-1]为止。

    缺点是无法探查到整个散列空间。

    c.双重散列法

    hi=(h(key)+i*h1(key)) % m,0 ≤ i ≤ m-1 

    基本思想是: 
    探查时从地址 d 开始,首先探查 T[d],然后依次探查 T[d+h1(d)], T[d + 2*h1(d)],…,等。

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

    定义 h1(key) 的方法较多,但无论采用什么方法定义,都必须使 h1(key) 的值和 m 互素,才能使发生冲突的同义词地址均匀地分布在整个表中,否则可能造成同义词地址的循环计算。

    该方法是开放定址法中最好的方法之一。

    哈希的应用

    • 哈希表
    • 分布式缓存

    哈希表(散列表)

    哈希表(hash table)是哈希函数最主要的应用。

    哈希表是实现关联数组(associative array)的一种数据结构,广泛应用于实现数据的快速查找。

    这里写图片描述

    用哈希函数计算关键字的哈希值(hash value),通过哈希值这个索引就可以找到关键字的存储位置,即桶(bucket)。哈希表不同于二叉树、栈、序列的数据结构一般情况下,在哈希表上的插入、查找、删除等操作的时间复杂度是 O(1)。

    查找过程中,关键字的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。因此,影响产生冲突多少的因素,也就是影响查找效率的因素。 
    影响产生冲突多少有以下三个因素:

    1. 哈希函数是否均匀;
    2. 处理冲突的方法;
    3. 哈希表的加载因子。

    哈希表的加载因子和容量决定了在什么时候桶数(存储位置)不够,需要重新哈希。

    加载因子太大的话桶太多,遍历时效率变低;太大的话频繁 rehash,导致性能降低。所以加载因子的大小需要结合时间和空间效率考虑。

    在 HashMap 中的加载因子为 0.75,即四分之三。

    分布式缓存

    网络环境下的分布式缓存系统一般基于一致性哈希(Consistent hashing)。简单的说,一致性哈希将哈希值取值空间组织成一个虚拟的环,各个服务器与数据关键字K使用相同的哈希函数映射到这个环上,数据会存储在它顺时针“游走”遇到的第一个服务器。可以使每个服务器节点的负载相对均衡,很大程度上避免资源的浪费。

    动态分布式缓存系统中,哈希算法的设计是关键点。使用分布更合理的算法可以使得多个服务节点间的负载相对均衡,可以很大程度上避免资源的浪费以及部分服务器过载。 使用带虚拟节点的一致性哈希算法,可以有效地降低服务硬件环境变化带来的数据迁移代价和风险,从而使分布式缓存系统更加高效稳定

    展开全文
  • 声明:本篇博客根据回顾老师上课...创建哈希表时,把关键字为k的元素直接存入地址为H(k)的单元,以后查找关键字为k的元素时,再利用哈希函数计算该元素的存储位置。再按关键字存取元素。Hash中存储的key值都是唯一的。

    声明:本篇博客根据回顾老师上课知识和书籍《数据结构——用C语言描述》(耿国华)整理得出,仅作知识回顾学习用。

    1.哈希法

    哈希法又称散列法、杂凑法、关键字地址计算法。相对应的表称为哈希表、散列表、或杂凑表等。

    哈希方法思想
    首先在元素的关键字k和元素的存储位置p之间建立一个对应关系H,使得 p = H(k),H成为哈希函数。创建哈希表时,把关键字为k的元素直接存入地址为H(k)的单元,以后查找关键字为k的元素时,再利用哈希函数计算该元素的存储位置。再按关键字存取元素。Hash中存储的key值都是唯一的。
    哈希冲突:
    当关键字集合很大的时候,关键字值不同的元素可能会映射到哈希表的同一个地址,即k1 != k2,H(k1) == H(k2),这种现象称为冲突,此时k1和k2为同义词。事实上冲突是不可避免的,由于关键字可能发生冲突的集合远远大于实际开辟的哈希表长度 ,构成冲突的必然性,可通过改进哈希的性能来减少冲突,即降低冲突的可能性。

    2.哈希函数的构造方法

    构造哈希函数原则
    (1)函数本身便于计算
    (2)计算出来的地址分布均匀,即对应任意一个关键字k,H(k)对应的不同地址的概率应该相同,以尽可能减少冲突

    在实际应用中,构造哈希函数要考虑以下五个因素:
    (1)计算哈希函数所需要的时间。哈希函数一定要简单,取放key值都需要根据哈希函数和key值计算位置,计算是要花时间的,尽可能要计算简单一点,这样计算时间也会少。
    (2)关键字的长度。关键字过长,我们可以考虑取关键的某几位来建立哈希函数。
    (3)哈希表的大小。哈希表可以减少查找次数,但是哈希表过短,或者过长都会使哈希法性能降低。
    (4)关键字分布情况。为了使key值和哈希函数计算出来的地址分布均匀,要考虑关键字分布情况建立合适哈希函数。
    (5)记录查找的频率。

    2.1数字分析法

    方法
    首先大概了解关键字集合。如果每个关键字的位数比哈希表的地址码位数多时,可以从key值选择分布均匀的若干位,构成哈希地址。
    比如哈希表长度为100,即地址空间为0~99,如果有200个key值,且key值都是8位十进制数d1d2d3d4d5d6d7d8,那么我们可以选择分布较均匀的两位数字作为key值。比如说所有key中,第二位和第五位数字都分布较均匀(即200个key值的第二位第五位都比较随机),那么我们就取d2d5作为key值地址码,比如 34982748,地址码为42。
    (在这里存在不相同的key值,但是地址码一样,这是哈希冲突,哈希冲突解决办法在最后给出。哈希表,一个地址码可以代表(存放)一组数据)。

    2.2平方取中法

    方法
    当无法确定关键字中哪几位分布较均匀时,可以求出关键字的平方值,再结合哈希表长度,取平方值的中间几位作为哈希地址(比如哈希表长度是 100,那哈希地址就00-99,我们就取key值平方后的中间2位作为地址码;如果哈希表长度是1000,那么哈希地址可以是000-999,那么就取key值平方后的中间3位作为地址码)。这是因为完成平方运算后,中间几位和关键字的每一位都相关,所以不同关键字会以较高的概率产生不同的哈希地址。

    2.3分段叠加法

    按哈希表地址位数将关键字分成位数相等的几部分(最后一部分可以较短),然后将这些部分相加,舍弃最高进位,剩下的数字作为地址码。比如哈希表长度为1000,可以表示地址码000-999。我们就把key值分成三位数为一部分。具体折叠方法有移位法和折叠法。以为叠加法直接将每一部分相加。折叠叠加法是将奇数段和偶数段分开,奇数段(偶数段)正常,偶数段(奇数段)倒序,再相加。

    举例:12360324711202065

    在这里插入图片描述

    2.4除留余数法

    顾名思义,即对key值进行取余。看有多少key值,如果有几十个key值,我们可以选择对10取余,对15取余,等等。余数就是对应的地址码。

    其实不论什么方法,目的都是为了在保证哈希函数尽可能简单的情况下让key值计算出来的地址码尽可能均匀。即让哈希表起到提高查找效率的作用。所以不管什么方法,只要达到最终这个目的就行。

    2.5伪随机数法

    即用一个为随机函数作为哈希函数p = H(key) = random(key)。

    3.处理冲突的方法

    3.1开放定址法

    也叫做再散列法
    思想:当关键字key的初始哈希地址p0 = H(key)出现冲突时(即该地址有key值了),以p0为基础,产生另一个地址p1,如果p1仍然冲突,再以p0为基础,产生另一个哈希地址p2…直至找到一个不冲突的地址pi,将key值存到里面。
    即hi = (h0 + di)%m
    m为表长,m为增量序列
    (1)线性探测再散列
    di = 1,2,3,4,…,m-1
    (2)二次探测再散列
    di = 1^2, -1^2, 2^2, -2^2,…, k^2, -k^2(k <= m/2)

    3.2再哈希法

    同时构造多个不同的哈希函数:
    Hi = RHi(key)
    哈希地址H1 = RH1(key)差生冲突时,再计算H2 = RH2(key)…直到冲突不再产生。

    3.3建立公共溢出区

    哈希表分为基本表溢出表两部分,凡是和基本表发生冲突的元素一律填入溢出表。

    3.4链地址法

    哈希表里每个表格是一个地址码和一个指针。将对应的key值都放在(key,指针)这种空间中,连接在对应的地址码后面。比如我们哈希表的地址码是key值对10取余。
    有数10,12 ,32,34,92,33,11,67,那么都映射到哈希表上,对应的结构为
    在这里插入图片描述
    结构体类型如下:

    #define TABLESIZE 10
    typedef int KeyType; // 键值的类型
    typedef struct
    {
    	KeyType key; // 学生信息 学号
    	//....其他数据成员 姓名
    	//....其他数据成员
    }DataType; // 存储的数据类型
    
    typedef struct
    {
    	DataType key;
    	KeyNode* next;
    }KeyNode;//key以这种结点方式被连接
    
    typedef struct Node
    {
    	int addcode;//地址码(0,1,2,3,...,9)
    	KeyNode* next;//指向KeyNode类型的结点
    }List;//哈希表每个格子的结构
    
    typedef struct Hash
    {
    	List* hash_table[TABLESIZE];
    }ListHash;//哈希表
    
    
    展开全文
  • 哈希函数构造方法与解决冲突的方法 哈希函数构造方法有:直接定址法、数字分析法、平方取中法、折叠法、除留余数法、随机数法等。 (1)直接定址法 其哈希函数为一次函数,即以下两种形式: H(key)= key 或者 ...

    哈希函数的构造方法与解决冲突的方法

    哈希函数的构造方法有:直接定址法、数字分析法、平方取中法、折叠法、除留余数法、随机数法等。
    (1)直接定址法
    其哈希函数为一次函数,即以下两种形式:
    H(key)= key 或者 H(key)= a * key + b
    其中 H(key)表示关键字为 key 对应的哈希地址,a 和 b 都为常数。

    (2)数字分析法
    如果关键字由多位字符或者数字组成,就可以考虑抽取其中的 2 位或者多位作为该关键字对应的哈希地址,在取法上尽量选择变化较多的位,避免冲突发生。

    (3)平方取中法
    平方取中法是对关键字做平方操作,取中间得几位作为哈希地址。此方法也是比较常用的构造哈希函数的方法
    例如关键字序列为{421,423,436},对各个关键字进行平方后的结果为{177241,178929,190096},则可以取中间的两位{72,89,00}作为其哈希地址。

    (4)折叠法
    折叠法是将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。此方法适合关键字位数较多的情况。

    (5)除留余数法
    若已知整个哈希表的最大长度 m,可以取一个不大于 m 的数 p,然后对该关键字 key 做取余运算,即:H(key)= key % p。
    在此方法中,对于 p 的取值非常重要,由经验得知 p 可以为不大于 m 的质数或者不包含小于 20 的质因数的合数。

    (6)随机数法
    是取关键字的一个随机函数值作为它的哈希地址,即:H(key)=random(key),此方法适用于关键字长度不等的情况。
    注意:这里的随机函数其实是伪随机函数,随机函数是即使每次给定的 key 相同,但是 H(key)都是不同;而伪随机函数正好相反,每个 key 都对应的是固定的 H(key)。

    如此多的构建哈希函数的方法,在选择的时候,需要根据实际的查找表的情况采取适当的方法。通常考虑的因素有以下几方面:
    ① 关键字的长度。如果长度不等,就选用随机数法。如果关键字位数较多,就选用折叠法或者数字分析法;反之如果位数较短,可以考虑平方取中法;
    ② 哈希表的大小。如果大小已知,可以选用除留余数法;
    ③ 关键字的分布情况;
    ④ 查找表的查找频率;
    ⑤ 计算哈希函数所需的时间(包括硬件指令的因素)。

    由于在子密钥的设计中哈希表的大小已知,我们选择除留余数法。

    对于哈希表的建立,需要选取合适的哈希函数,到那时对于无法避免的冲突,需要采取适当的措施去处理。
    通常用的处理冲突的方法有以下几种:开放定址法、再哈希法、链地址法、建立一个公共溢出区等。

    (1)开放定址法
    H(key)=(H(key)+ d)MOD m(其中 m 为哈希表的表长,d 为一个增量)
    当得出的哈希地址产生冲突时,选取以下 3 种方法中的一种获取 d 的值,然后继续计算,直到计算出的哈希地址不在冲突为止,这 3 种方法为:

    ① 线性探测法:d=1,2,3,…,m-1
    ② 二次探测法:d=12,-12,22,-22,32,…
    ③ 伪随机数探测法:d=伪随机数

    例如,在长度为 11 的哈希表中已填写好 17、60 和 29 这 3 个数据(如图 2(a) 所示),其中采用的哈希函数为:H(key)=key MOD 11,现有第 4 个数据 38 ,当通过哈希函数求得的哈希地址为 5,与 60 冲突,则分别采用以上 3 种方式求得插入位置如图 2(b)所示:

    哈希函数的构造方法有:直接定址法、数字分析法、平方取中法、折叠法、除留余数法、随机数法等。
    (1)直接定址法
    其哈希函数为一次函数,即以下两种形式:
    H(key)= key 或者 H(key)= a * key + b
    其中 H(key)表示关键字为 key 对应的哈希地址,a 和 b 都为常数。

    (2)数字分析法
    如果关键字由多位字符或者数字组成,就可以考虑抽取其中的 2 位或者多位作为该关键字对应的哈希地址,在取法上尽量选择变化较多的位,避免冲突发生。

    (3)平方取中法
    平方取中法是对关键字做平方操作,取中间得几位作为哈希地址。此方法也是比较常用的构造哈希函数的方法
    例如关键字序列为{421,423,436},对各个关键字进行平方后的结果为{177241,178929,190096},则可以取中间的两位{72,89,00}作为其哈希地址。

    (4)折叠法
    折叠法是将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。此方法适合关键字位数较多的情况。

    (5)除留余数法
    若已知整个哈希表的最大长度 m,可以取一个不大于 m 的数 p,然后对该关键字 key 做取余运算,即:H(key)= key % p。
    在此方法中,对于 p 的取值非常重要,由经验得知 p 可以为不大于 m 的质数或者不包含小于 20 的质因数的合数。

    (6)随机数法
    是取关键字的一个随机函数值作为它的哈希地址,即:H(key)=random(key),此方法适用于关键字长度不等的情况。
    注意:这里的随机函数其实是伪随机函数,随机函数是即使每次给定的 key 相同,但是 H(key)都是不同;而伪随机函数正好相反,每个 key 都对应的是固定的 H(key)。

    如此多的构建哈希函数的方法,在选择的时候,需要根据实际的查找表的情况采取适当的方法。通常考虑的因素有以下几方面:
    ① 关键字的长度。如果长度不等,就选用随机数法。如果关键字位数较多,就选用折叠法或者数字分析法;反之如果位数较短,可以考虑平方取中法;
    ② 哈希表的大小。如果大小已知,可以选用除留余数法;
    ③ 关键字的分布情况;
    ④ 查找表的查找频率;
    ⑤ 计算哈希函数所需的时间(包括硬件指令的因素)。

    由于在子密钥的设计中哈希表的大小已知,我们选择除留余数法。

    对于哈希表的建立,需要选取合适的哈希函数,到那时对于无法避免的冲突,需要采取适当的措施去处理。
    通常用的处理冲突的方法有以下几种:开放定址法、再哈希法、链地址法、建立一个公共溢出区等。

    (1)开放定址法
    H(key)=(H(key)+ d)MOD m(其中 m 为哈希表的表长,d 为一个增量)
    当得出的哈希地址产生冲突时,选取以下 3 种方法中的一种获取 d 的值,然后继续计算,直到计算出的哈希地址不在冲突为止,这 3 种方法为:

    ① 线性探测法:d=1,2,3,…,m-1
    ② 二次探测法:d=12,-12,22,-22,32,…
    ③ 伪随机数探测法:d=伪随机数

    例如,在长度为 11 的哈希表中已填写好 17、60 和 29 这 3 个数据(如图 2(a) 所示),其中采用的哈希函数为:H(key)=key MOD 11,现有第 4 个数据 38 ,当通过哈希函数求得的哈希地址为 5,与 60 冲突,则分别采用以上 3 种方式求得插入位置如图 2(b)所示:

    哈希函数的构造方法有:直接定址法、数字分析法、平方取中法、折叠法、除留余数法、随机数法等。
    (1)直接定址法
    其哈希函数为一次函数,即以下两种形式:
    H(key)= key 或者 H(key)= a * key + b
    其中 H(key)表示关键字为 key 对应的哈希地址,a 和 b 都为常数。

    (2)数字分析法
    如果关键字由多位字符或者数字组成,就可以考虑抽取其中的 2 位或者多位作为该关键字对应的哈希地址,在取法上尽量选择变化较多的位,避免冲突发生。

    (3)平方取中法
    平方取中法是对关键字做平方操作,取中间得几位作为哈希地址。此方法也是比较常用的构造哈希函数的方法
    例如关键字序列为{421,423,436},对各个关键字进行平方后的结果为{177241,178929,190096},则可以取中间的两位{72,89,00}作为其哈希地址。

    (4)折叠法
    折叠法是将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。此方法适合关键字位数较多的情况。

    (5)除留余数法
    若已知整个哈希表的最大长度 m,可以取一个不大于 m 的数 p,然后对该关键字 key 做取余运算,即:H(key)= key % p。
    在此方法中,对于 p 的取值非常重要,由经验得知 p 可以为不大于 m 的质数或者不包含小于 20 的质因数的合数。

    (6)随机数法
    是取关键字的一个随机函数值作为它的哈希地址,即:H(key)=random(key),此方法适用于关键字长度不等的情况。
    注意:这里的随机函数其实是伪随机函数,随机函数是即使每次给定的 key 相同,但是 H(key)都是不同;而伪随机函数正好相反,每个 key 都对应的是固定的 H(key)。

    如此多的构建哈希函数的方法,在选择的时候,需要根据实际的查找表的情况采取适当的方法。通常考虑的因素有以下几方面:
    ① 关键字的长度。如果长度不等,就选用随机数法。如果关键字位数较多,就选用折叠法或者数字分析法;反之如果位数较短,可以考虑平方取中法;
    ② 哈希表的大小。如果大小已知,可以选用除留余数法;
    ③ 关键字的分布情况;
    ④ 查找表的查找频率;
    ⑤ 计算哈希函数所需的时间(包括硬件指令的因素)。

    由于在子密钥的设计中哈希表的大小已知,我们选择除留余数法。

    对于哈希表的建立,需要选取合适的哈希函数,到那时对于无法避免的冲突,需要采取适当的措施去处理。
    通常用的处理冲突的方法有以下几种:开放定址法、再哈希法、链地址法、建立一个公共溢出区等。

    (1)开放定址法
    H(key)=(H(key)+ d)MOD m(其中 m 为哈希表的表长,d 为一个增量)
    当得出的哈希地址产生冲突时,选取以下 3 种方法中的一种获取 d 的值,然后继续计算,直到计算出的哈希地址不在冲突为止,这 3 种方法为:

    ① 线性探测法:d=1,2,3,…,m-1
    ② 二次探测法:d=12,-12,22,-22,32,…
    ③ 伪随机数探测法:d=伪随机数

    例如,在长度为 11 的哈希表中已填写好 17、60 和 29 这 3 个数据(如图 2(a) 所示),其中采用的哈希函数为:H(key)=key MOD 11,现有第 4 个数据 38 ,当通过哈希函数求得的哈希地址为 5,与 60 冲突,则分别采用以上 3 种方式求得插入位置如图 2(b)所示:

    在这里插入图片描述
    注:在线性探测法中,当遇到冲突时,从发生冲突位置起,每次 +1,向右探测,直到有空闲的位置为止;二次探测法中,从发生冲突的位置起,按照 +12,-12,+22,…如此探测,直到有空闲的位置;伪随机探测,每次加上一个随机数,直到探测到空闲位置结束。

    (2)再哈希法
    当通过哈希函数求得的哈希地址同其他关键字产生冲突时,使用另一个哈希函数计算,直到冲突不再发生。

    (3)链地址法
    将所有产生冲突的关键字所对应的数据全部存储在同一个线性链表中。例如有一组关键字为{19,14,23,01,68,20,84,27,55,11,10,79},其哈希函数为:H(key)=key MOD 13,使用链地址法所构建的哈希表如图 3 所示:

    在这里插入图片描述
    (4)建立一个公共溢出区
    建立两张表,一张为基本表,另一张为溢出表。基本表存储没有发生冲突的数据,当关键字由哈希函数生成的哈希地址产生冲突时,就将数据填入溢出表。

    展开全文
  • 常见的六种哈希构造函数

    千次阅读 2021-02-23 09:46:53
    文章目录相关概念介绍一、直接寻址法二、数字分析法三、折叠法四、平方取中法五、除留余数法...简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。 散列表: 散列表(Hash table,也叫哈希表),是.

    相关概念介绍

    • 哈希:
      Hash,一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
    • 散列表:
      散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
    • 哈希冲突:
      由于哈希算法被计算的数据是无限的,而计算后的结果范围有限,因此总会存在不同的数据经过计算后得到的值相同,这就是哈希冲突。

    一、直接寻址法

    • 介绍:取关键字或关键字的某个线性函数值为散列地址,即H(key)=key或者H(key)=a*key+b(a,b为常数)。
    • 举例:[‘A’,‘B’,‘D’,‘A’,‘C’,‘E’,‘F’,‘C’] ,求该字符数组里每个字符的出现次数(数组中只有大写字母)。
    • 分析:我们可以知道’A’-'Z’的ASCLL码是65-90,则哈希函数可以通过直接寻址法H(key)=key-‘A’(对应定义中的a=1,b=-‘A’即65),这样针对每一个key,都可以将它的H(key)值当成数组下标放在一个长度为26的int数组中统计长度
      假设字符数组为a,int数组为b。即b[a[i]-‘A’]++(i表示a数组的下标索引)。
    • 结果
      b[0]=2(代表A出现两次);b[1]=1(代表B出现一次),b[2]=2(代表C出现两次)…

    二、数字分析法

    • 介绍:分析一组数据中相同位(个位,十位,百位…)的数字出现频率,如果该位数字出现结果较为集中,如果取其作为构造散列地址的依据则很容易出现哈希冲突,反之,如果该位数字出现结果较为平均,则取其作为构造散列地址的依据则不容易出现哈希冲突。
    • 举例:某公司招聘了一些实习生,其生日分别为[19990104,20000910,20000315,20001128,20001014,19990413,19990920,20000517],对其进行hash处理。
    • 分析
      如果取8位数作为散列地址,虽然很难出现哈希冲突,但是空间浪费很大,因此考虑只取其中几位作为散列地址,即能减少空间浪费又能降低哈希冲突的可能性,观察上面8组数据,前4位集中在1999,2000,如果取前4位则很容易出现哈希冲突,而后四位分布相对分散,不容易出现哈希冲突,因此取后四位比较符合
    • 结果
      H(19990104)=104,H(20000910)=910,H(20000315)=315…

    三、折叠法

    • 介绍:折叠法是把关键字值自左向右分成位数相等的几部分,每一部分的位数应与散列表地址的位数相同,只有最后一部分的位数可以短一些。把这些部分的数据叠加起来(去除进位),就可以得到关键字值的散列地址。
      有两种叠加方法:
      (1)移位法(shift floding):把各部分的最后一位对齐相加。
      (2)分界法(floding at the boudaries):沿各部分的分界来回折叠,然后对其相加。
    • 举例:key=1234791,散列地址为2位
    • 分析
      将key分成12,34,79,1四部分
      (1)移位法:12+34+79+1
      (2)分界法:12+43+79+1(即第偶数个加数和移位法反过来)
    • 结果
      (1)移位法:H(1234791)=35(相加为135,去除进位1)
      (2)分界法:H(1234791)=44(相加为144,去除进位1)

    四、平方取中法

    • 介绍:当无法确定关键字中哪几位分布较均为时,可以求出关键字的平方值,然后按需要取平方值的中间几位作为散列地址。这是因为:平方后中间几位和关键字中每一位都有关,故不同关键字会以较高的概率产生不同的散列地址。
    • 举例:关键字序列:{3213,3113,3212,4312}。
    • 分析:
      3213^2=10323369
      3113^2=9690769
      3212^2=10316944
      4312^2=18593344
      取平方值中间4位为散列地址(3113的平方值前面补0凑成8位)
    • 结果
      H(3213)=3233,H(3113)=6907,H(3212)=3169,H(4312)=5933

    五、除留余数法

    • 介绍:取关键字被某个不大于散列表表长m的数p除后的余数作为散列地址,即H(key)=key mod p(p<=m),该方法不仅可以直接对关键字取模,还可以在折叠,平方取中等方法后再取模。注意:p的选择很重要,一般选取满足条件(即p<=m)的最大质数或者m,如果取的不好容易产生哈希冲突。
    • 举例:关键字序列:{16,11,19,23,2,6,10},散列表表长为11。
    • 分析
      该散列表表长刚好为质数,直接选择p=11
    • 结果:
      H(16)=5, H(11)=0, H(19)=8, H(23)=1, H(2)=2, H(6)=6, H(10)=10

    六、随机数法

    • 介绍:选择一随机函数,取关键字作为随机函数的种子,生成随机值作为散列地址,即H(key)=random (key),其中random为随机函数,通常用于关键字长度不同的场合。
    • 举例:key=123,随机函数为每位数字平方后连续相乘。
    • 分析
      随机函数的选择对于哈希冲突的概率很重要,这里只是简单的选择一个函数
    • 结果
      H(123)=36
    展开全文
  • 2哈希函数构造方法 1、直接定址法 直接根据数据的值来映射到地址,比如对数字10、11、12、13…可以将其映射到一块连续的内存中。 2、数字分析法 根据数据的某些数字(比如百位和十位数字)来映射到地址。
  • 哈希算法(哈希函数)基本

    千次阅读 2021-09-19 16:33:42
    一、什么是哈希(Hash) 哈希也称“散列”函数或“杂凑”函数。它是一个不可逆的单向映射,将任意长度的输入消息M...这是哈希函数安全性的基础。 灵敏性:对输入数据敏感,哪怕只改了一个Bit,得到的哈希值也大不相同
  • 常用哈希函数介绍

    千次阅读 2021-03-31 16:21:32
    哈希函数介绍 什么是哈希?在记录的关键字与记录的存储地址之间建立的一种对应关系叫哈希函数哈希函数就是一种映射,是从关键字到存储地址的映射。 通常,包含哈希函数的算法的算法复杂度都假设为O(1),这就是为...
  • 先确定选题,待写。。。
  • 文章目录哈希表的概念哈希表散列法存储的基本思想优点缺点哈希方法(杂凑法)哈希函数(杂凑函数)哈希表(杂凑表)冲突哈希方法必须解决以下两个问题构造好的哈希函数制定一个好的解决冲突的方案哈希函数构造方法直接定...
  • 哈希函数介绍

    2021-11-01 18:37:25
    哈希函数介绍 什么是哈希 在记录的关键字与记录的存储地址之间建立的一种对应关系叫哈希函数哈希函数就是一种映射,是从关键字到存储地址的映射。 通常,包含哈希函数的算法的算法复杂度都假设为 O(1),这...
  • 文章目录一、实验题目二、需求分析三、概要设计四、调试分析五、使用说明六、测试结果七、其他...哈希函数用除留余数法构造,用线性探测再散列法或链地址法处理冲突。 [测试数据] 取读者周围较熟悉的 30 个人名。 [选
  • 哈希函数和数字签名

    2021-09-13 18:54:27
    目录1 哈希函数 Hash1.1 构造方法1.2 哈希函数在密码学的应用2 数字签名2.1 签名--认证流程2.2 一个生动形象的例子 在讲数字前面以前,我们先要了解一下哈希函数 1 哈希函数 Hash Hash,一般翻译做散列、杂凑,或...
  • 哈希函数+解决冲突的方法 构造方法 直接定址法,除留余数法 解决冲突的方法 开放定址法:线性探测法,平方探测法 拉链法 1、散列表的若干术语 散列方法(杂凑法) 选取某个函数,依该函数按关键字计算元素的存储位置...
  • 细嗑 哈希函数(散列函数) 和 哈希表(散列表) 1、初识哈希函数 和 哈希表 在线性表(数组、链表)和树结构中,记录存储的位置是随机的,也就是说在记录存储的位置和记录的关键字之间没有一 一对应的关系。 假设...
  • 文章目录哈希哈希(散列)函数 哈希 哈希(散列)是一种数据结构,通过散列算法将元素值转换为散列值进行存储。使得元素存储的位置与元素...哈希函数计算出来的地址能均匀分布在整个空间中(防止产生密集的哈希冲突
  • /*1、输入10个一百以内的数,用x%15作为哈希函数, 采用线性探测法作为冲突处理方法,将数据逐个放入大小为15的数组中。 输出散列表的存储示意图(第一行输出下标,第二行输出横线,第三行输出数据)。 并对其进行...
  • 已知一组关键字(19,14,23,1,68,20,84,27,55,11,10,79),哈希函数定义为:H(key)=key MOD 13, 哈希表长为m=16。实现该哈希表的散列,并计算平均查找长度(设每个记录的查找概率相等)。 (1)哈希表定义为定长的数组...
  • 哈希函数

    2021-05-12 19:29:39
    关于哈希函数 哈希函数 一种函数H,根据这个函数和查找关键字key,可以直接确定查找值所在位置,这个函数就是哈希函数,而哈希表是基于哈希函数建立的一种查找表 哈希冲突 对应不同的关键字(数值)可能获得相同的...
  • 哈希函数和哈希表

    2021-01-16 11:00:42
    哈希函数的算法的原理是超纲的内容(底层的实现是位运算),常见的哈希算法有扩展MD5(返回2^ 64)、SHA1(返回2^128)(哈希函数的实现有数千种实现方法) 经典实现中,桶后跟的是链表,Java中的实现,实际上不是O(1...
  • 哈希表核心思想就是python的字典,需要存储的对象就是字典的value,对象的关键字就是字典的键,通过哈希函数把字典的键映射到一个内存地址上,然后内存地址里存储的就是对象。—哈希函数构建的是地址。 哈希表(散...
  • 文章目录定义域扩展:The Merkle-Damg˚ard Transform使用Hash函数的消息认证 定义 Hash函数简单定义:接受一定长度的输入并压缩成短而固定长度的输出的函数 好的Hash函数:有较弱的碰撞性(碰撞是一定存在的,因为...
  • 哈希函数构造原则是:函数本身便于计算、计算出来的地址分布均匀(即对任意K,f(K)对应不同地址的概率相等)。 1. 除留余数法 取关键字被某个不大于哈希表长m的数p除后所得的余数为哈希地址。即: H(key)=key ...
  • 解决哈希冲突(四种方法

    千次阅读 2021-07-09 19:21:49
    哈希冲突:当两个不同的数经过哈希函数计算后得到了同一个结果,即他们会被映射到哈希表的同一个位置时,即称为发生了哈希冲突。简单来说就是哈希函数算出来的地址被别的元素占用了。 二、解决哈希冲突办法 1、...
  • 散列函数构造: 1.直接定址法: 这里的例子中 h(key)=key-1990 2.除留余数法: 3.数字分析法 身份证号码中有几位是随机的: 处理冲突的方法 开放定址法 缺点:聚集现象,一部分值集中在一块 .....
  • 散列函数构造方法

    2021-03-02 09:11:11
    数字关键词的散列函数构造 1.直接定址法 取关键词的某个线性函数值为散列地址,h(key)=a*key+b (a、b为常数) 2.除留取余法 h(key)=key mod p p是散列表的大小,一般是素数 3.数字分析法 分析数字关键字在各位上的...
  • 文章目录前言1、哈希表与哈希函数的引入2、哈希表一、设计1、一般、通用哈希函数的设计2、默认哈希函数二、哈希冲突1、链地址法。(seperate chaining )1、1实现1.2、测试2、哈希表的动态空间优化参考 前言 1、哈希...
  • 解决哈希碰撞的方法

    2021-08-12 17:11:54
    根据设定的哈希函数H(key)和处理冲突的方法将一组关键字映像到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这种表便称为哈希表,这一映像过程称为哈希造表或者散列,...
  • 链地址法:将所有关键字为同义词的记录保存在一个线性链表中(拉链法)设某哈希函数产生的哈希地址在区间[0,12]上,则创建指针数组add[12],其中每个元素都是一个单项链表的头结点(有值)。由于仅仅是简单的实现。。...
  • 这里的对应关系f就是散列函数,也称为哈希函数; 所以哈希表定义也可以是 通过 关键字集合 由 哈希函数 推出 存储地址集合; 而这些集合的存储空间就是散列表(哈希表); 散列技术既是一种存储方法也是一种查找方法...
  • 哈希表与哈希查找

    2021-08-28 14:07:36
    哈希表(哈希查找) ...文章目录哈希表(哈希查找)哈希表概念哈希函数构造方法直接定址法数字分析法平方取中法折叠法除留余数法处理冲突开放定址法线性探测二次探测再哈希法链地址法性能分析 哈希表概念 ​ 哈希表,

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 84,545
精华内容 33,818
关键字:

哈希函数的构造方法