python之哈希算法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python之哈希算法相关的知识,希望对你有一定的参考价值。

参考技术A 哈希(Hash)算法:`hash(object)`

哈希算法将一个不定长的输入,通过散列函数变换成一个定长的输出,即散列值。是一种信息摘要算法。对象的hash值比原对象拥有更低的内存复杂度。

它不同于加密。哈希(hash)是将目标文本转换成具有相同长度的,不可逆的杂凑字符串,而加密则是将文本转换为具有相同长度的,可逆的密文。

哈希(hash)算法是不可逆的,只能由输入产生输出,不能由输出产生输入。而加密则是可逆的。即可以从输入产生输出,也可以反过来从输出推出输入。

对于hash算法,不同的数据应该生成不同的哈希值。如果两个不同的数据经过Hash函数计算得到的Hash值一样。就称为哈希碰撞(collision)。哈希碰撞无法被完全避免。只能降低发生概率。

好的hash函数会导致最少的hash碰撞。

*

可哈希性(hashable):

可哈希的数据类型为不可变的数据结构(如字符串srt,元组tuple,对象集objects等)。这种数据被称为可哈希性。

不可哈希性:

不可哈希的数据类型,为可变的数据结构(如字典dict,列表list和集合set等)。

如果对可变的对象进行哈希处理,则每次对象更新时,都需要更新哈希表。这样我们则需要将对象移至不同的数据集,这种操作会使花费过大。

因此设定不能对可变的对象进行hash处理。

**

**

Python3.x添加了hash算法的随机性,以提高安全性,因此对于每个新的python调用,同样的数据源生成的结果都将不同。

哈希方法有(MD5, SHA1, SHA256与SHA512等)。常用的有SH256与SHA512。MD5与SHA1不再常用。

- MDH5 (不常用)

- SHA1 (不常用)

- SHA256 (常用)

- SHA512 (常用)

一种局部敏感的hash算法,它产生的签名在一定程度上可以表征原内容的相似度。

> 可以被用来比较文本的相似度。

安装simhash:

Pip3 install simhash

感知哈希算法(perceptual Hash Algorithm)。用于检测图像和视频的差异。

安装Imagehash:

pip3 install Imagehash

比较下面两张图片的Imagehash值

可以看到两张图片的hash值非常相似。相似的图片可以生成相似的哈希值是Imagehash的特点。

Python算法哈希存储哈希表散列表原理

哈希表的定义:

  哈希存储的基本思想是以关键字Key为自变量,通过一定的函数关系(散列函数或哈希函数),计算出对应的函数值(哈希地址),以这个值作为数据元素的地址,并将数据元素存入到相应地址的存储单元中。

  查找时再根据要查找的关键字采用同样的函数计算出哈希地址,然后直接到相应的存储单元中去取要找的数据元素即可。

哈希表的应用:

  哈希表(hash table)是实现字典操作的一种有效的数据结构。

  尽管最坏的情况下,散列表中查找一个元素的时间与链表中查找的时间相同,达到了O(n)。

  然而实际应用中,散列的查找的性能是极好的。在一些合理的假设下,在散列表中查找一个元素的平均时间是O(1)。

建立哈希表操作步骤:

  1) step1 取数据元素的关键字key,计算其哈希函数值(地址)。若该地址对应的存储空间还没有被占用,则将该元素存入;否则执行step2解决冲突。

  2) step2 根据选择的冲突处理方法,计算关键字key的下一个存储地址。若下一个存储地址仍被占用,则继续执行step2,直到找到能用的存储地址为止。

 

常用的哈希函数:

  构造哈希函数的方法有很多,总的原则是尽可能将关键字集合空间均匀的映射到地址集合空间中,同时尽可能降低冲突发生的概率。

1、除留余数法:

  H(Key) = key % p  (p ≤ m)

  取关键字除以p的余数作为哈希地址,p最好选择一个小于或等于m(哈希地址集合的个数)的某个最大素数

哈希表长度 8 16 32 64 128 256 512
最大素数 7 13 31 61 127 251 503

2、直接地址法

  H(Key) = a * Key + b;这个“a,b”是常量。

3、数字分析法

  比如有一组key1=112233,key2=112633,key3=119033,

  针对这样的数我们分析数中间两个数比较波动,其他数不变。那么我们取key的值就可以是 key1=22,key2=26,key3=90。

4、平方取中法

  此处忽略,见名识意。

5、折叠法

  比如key=135790,要求key是2位数的散列值。那么我们将key变为13+57+90=160,然后去掉高位“1”,此时key=60,

  这就是他们的哈希关系,这样做的目的就是地址与每一位的key都相关,来做到“散列地址”尽可能分散的目地。

冲突处理方法:

  影响哈希查找效率的一个重要因素是哈希函数本身。当两个不同的数据元素的哈希值相同时,就会发生冲突。为减少发生冲突的可能性,哈希函数应该将数据尽可能分散地映射到哈希表的每一个表项中。

  解决冲突的方法有以下两种: 

  (1) 开放地址法  

    如果两个数据元素的哈希值相同,则在哈希表中为后插入的数据元素另外选择一个表项。

    当程序查找哈希表时,如果没有在第一个对应的哈希表项中找到符合查找要求的数据元素,程序就会继续往后查找,直到找到一个符合查找要求的数据元素,或者遇到一个空的表项。  

    ①.线性探测法

      这种方法在解决冲突时,依次探测下一个地址,直到有空的地址后插入,若整个空间都找遍仍然找不到空余的地址,产生溢出。

      Hi =( H(Key) + d) % m                    ( i = 1,2,3,...,k , k ≤ m-1 )

      地址增量 d= 1,2,...,m-1 , 其中 i 为探测次数

    ②.二次探测法

      地址增量序列为:d= 12,-12,22,-22 ,...,q2,-q2  (q ≤ m/2)

    ③.双哈希函数探测法

      Hi =( H(Key) + i * RH(Key) ) % m      ( i = 1,2,3,..., m-1 )

      H(Key) , RH(Key) 是两个哈希函数,m为哈希表长度。

      先用第一个哈希函数对关键字计算哈希地址,一旦产生地址冲突,再用第二个函数确定移动的步长寅子,最后通过步长因子序列由探测函数寻找空余的哈希地址。

      H1 = ( a+b )%m , H2 = ( a + 2b )%m , ... , Hm-1 = ( a+(m-1)*b )%m

  (2) 链地址法

    将哈希值相同的数据元素存放在一个链表中,在查找哈希表的过程中,当查找到这个链表时,必须采用线性查找方法。

    技术分享

 

Python字典dict的实现 是使用开放寻址法中的二次探查来解决冲突的。

?? 参考链接

 

以上是关于python之哈希算法的主要内容,如果未能解决你的问题,请参考以下文章

人工智能算法之哈希算法

python hash()和哈希算法

查找算法系列之复杂算法:哈希查找

区块链之哈希算法(完整篇)

大白话之哈希表和哈希算法

Python算法哈希存储哈希表散列表原理