Python数据结构与算法55:排序与查找:散列函数设计

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

本文阅读时间约为6分钟

本节介绍两种散列函数设计方法:折叠法和平方取中法。

散列函数设计:折叠法

折叠法设计散列函数的基本步骤是:

将数据按照位数分为若干段,再将几段数字相加,最后对散列表大小求余,得到散列值。

例如,我们要保存一个电话号码62767255。

先按每两位将这8位数分为4段(62、76、72、55)。

4段数字相加(62+76+72+55=265)。

散列表包括0~11等11个槽,那么就是265/11=1。

所以h(62767255)=1,该电话号码的散列值为1,也就是说,应该存放在1号槽。

有时候折叠法还会包括一个隔数反转的步骤。比如上述的(62、76、72、55)隔数反转为(62、67、72、55),即隔数的76和55分别反转为67和55。

然后再累加(62+67+72+55=256)。

接着对11求余(256%11=3),所以h'(62767255)=3。

一般而言,隔数反转从理论上看并没必要,但是它确实为折叠法得到散列函数提供了一种微调手段,有时得到的结果能更好地符合散列特性。

散列函数设计:平方取中法

平方取中法,首先将数据项做平方运算,然后取平方数的中间两位,再对散列表的大小求余。

例如,用平方取中法对44进行散列。

首先44*44=1936,然后取1936这个数中间的两位——93,再对散列表大小11求余,最后得到44的散列值93%11=5。

平方取中法和求余法散列函数的对比

两种散列函数都是完美散列函数,分散度都很好。只是相比求余法,平方取中法计算量稍大。

数据项 求余法 平方取中法
54       10        3
26        4        7
93        5        9
17        6        8
77        0        4
31        9        6
非数字型数据项的散列函数设计

前面说的都是数字型数据项的散列函数设计。那么对于非数字型数据项,我们如何求其散列值?

对于非数字型数据项,我们可以把数据项中的每个字符看作是ASCII码即可。
如要求cat的散列值,采用如下步骤:

把数据项中的每个字符看作是ASCII码,求其数字:ord('c')=99,ord('a')=96,ord('t')=116。

再将这些整数累加:99+97+116=312。

最后用累加之和对散列表大小求余,得到cat的散列值:312%11=4。

参考代码如下:

def hash(aString, tableSize):
    r = 0
    for pos in range(len(aString)):
        r += ord(aString[pos])
    return r % tableSize

print(hash('cat', 11))

<<<4

当然,这种方法有一个问题,那就是所有的变位词(如cat和tac,组成的字符及分别的数量一样,就是变位词),其散列值是一样的。

为了防止出现这种问题,可以根据字符串所在位置作赋予不同的权重因子,再乘以ord值。

用这种改善后的方法来计算cat的散列值,就有:

ord('c')*1+ord('a')*2+ord('t')*3=641。

641%11=3。

除了上述的散列函数设计方法外,我们还可以设计出更多的散列函数方法,但要坚持的一个基本出发点——散列函数不能成为存储和查找过程中的计算负担。

如果散列函数设计太过复杂,要花费大量的计算资源计算槽号,这样就失去了散列本身的意义,可能还不如简单地进行顺序查找或二分查找。

To be continued.

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

推荐阅读更多精彩内容