Python数据结构与算法53:排序与查找:完美散列函数

:本文如涉及到代码,均经过Python 3.7实际运行检验,保证其严谨性。

本文阅读时间约为5分钟

在解决散列表的冲突问题之前,我们先介绍完美散列函数。

什么是完美散列函数

给定一组数据项,如果一个散列函数能把每个数据项映射到不同的槽中,那么这个散列函数就可以称为完美散列函数

对于固定的一组数据,总是能想办法设计出完美散列函数。但是,如果数据项经常性地变动,很难有一个系统性的方法来设计对应的完美散列函数。此时就会出现冲突(collision)。

当然,冲突也不是致命性的错误,同样有办法处理。

获得完美散列函数的一种方法是,扩大散列表的容量,大到所有可能出现的数据项都能够占据不同的槽。但是,很显然,这种方法在数据项范围过大的情况下不太实用,会浪费太多存储空间,这种代价太大。

所以,我们采用折中的方案。好的散列函数需要具备特性:

  • 冲突最少(近似完美)。
  • 计算难度低(额外开销小)。
  • 充分分散数据项(节约空间)。
完美散列函数的更多用途

除了用于在散列表中安排数据项的存储位置,散列技术还用在信息处理的很多领域。

由于完美散列函数能够对任何不同的数据生成不同的散列值,如果把散列值当作数据的“指纹”或者“摘要”,这种特性被广泛应用在数据的一致性校验上。

由任意长度的数据生成固定长度的“指纹”,并要求具备唯一性,这在数学上是无法做到的。但是,设计巧妙的“准完美”散列函数却能在实用范围内做到这一点。

作为一致性校验的数据“指纹”函数需要具备以下特性:

  • 压缩性——任意长度的数据,得到的“指纹”长度是固定的。
  • 易计算性——丛原数据计算“指纹”很容易;从指纹计算原数据是不可能的。
  • 抗修改性——对原数据的微小改动,都会引起“指纹”的大改变。
  • 抗冲突性——已知原数据和“指纹”,要找到相同指纹的数据(伪造)是非常困难的。
散列函数MD5/SHA

最著名的近似完美散列函数是MD5和SHA系列函数。

MD5(Message Digest)将任何长度的数据变换为固定长度为128位(16字节)的“摘要”。

128位二进制已经是一个极为巨大的数字空间:据说是地球沙粒的数量级别。

SHA(Secure Hash Algorithm)是另一组散列函数。

SHA-0/SHA-1输出散列值160位(20字节)。

SHA-256/SHA-224分别输出256位、224位。

SHA-512/SHA-384分别输出512位和384位。

160位,相当于10的48次方,地球水分子数量估计是10的47方。

256位二进制相当于10的77次方,已知宇宙所有基本粒子大约是10的72次方到87次方之间。

虽然近年来发现MD5/SHA-0/SHA-1三种散列函数能以极其特殊的情况来构造个别碰撞(散列冲突),但在实际应用中从未有过实际的威胁。

Python的散列函数库hashlib

Python自带MD5和SHA系列的散列函数库:hashlib,该库包括了md5/sha1/sha224/sha256/sha384/sha512等6种散列函数。

import hashlib

# 128位散列值。
hashlib.md5("Hello, World!".encode('utf-8')).hexdigest()
Out[6]: '65a8e27d8879283831b664bd8b7f0ad4'


# 160位散列值。
hashlib.sha1("Hello, World!".encode('utf-8')).hexdigest()
Out[7]: '0a0a9f2a6772942557ab5355d76af442f8f65e01'

无论多么长的字符串,只要使用同一散列函数库,返回的位数都是固定的。如下所示:

hashlib.md5("Are you OK?".encode('utf-8')).hexdigest()
Out[9]: 'eb48ea947c28cb870b638855e2bdbcca'

hashlib.md5("Don't be a cutie pie!".encode('utf-8')).hexdigest()
Out[10]: 'a14615484f10095a3f1af379f7dc7d50'

hashlib.md5("No one knows the new coronavirus better than me.".encode('utf-8')).hexdigest()
Out[11]: 'e4fe757217d4bda4aedb95790608a632'

hashlib.md5("没人比我更懂新冠病毒。".encode('utf-8')).hexdigest()
Out[12]: '90dd6c2d5bd6f67ebc42561031742785'

除了对单个的字符串进行计算之外,hashlib库还支持用update方法来对任意长的数据分部分来计算。无论多大的数据,都不会有内存不足的问题。如下所示:

m = hashlib.md5()

m.update("Hello, World!".encode('utf-8'))

m.update("This is part # 2!".encode('utf-8'))

m.update("This is part # 3!".encode('utf-8'))

m.hexdigest()
Out[20]: 'd9b68147bdb0945676799c26039ac4e8'
完美散列函数的应用

完美散列函数用于数据一致性校验,有以下应用:

  • 数据文件一致性判断。
  • 为每个文件计算其散列值,仅对比其散列值即可得知文件内容是否相同。
  • 用于网络文件下载完整性校验。
  • 用于文件分享系统:比如网盘中相同的文件可以无需存储多次。
  • 加密形式保存密码。
  • 仅保存密码的散列值,用户输入密码后,计算散列值并比对。
  • 无需保存密码的明文即可判断用户是否输入了正确的密码。
  • 防止文件篡改:原理同数据文件一致性的判断。防止篡改是电子商务的信息技术基础。

To be continued.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,907评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,546评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,705评论 0 238
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,624评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,940评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,371评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,672评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,396评论 0 195
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,069评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,350评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,876评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,243评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,847评论 3 231
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,004评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,755评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,378评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,266评论 2 259

推荐阅读更多精彩内容