hash函数查找和ASL计算
Hash表的“查找成功的ASL”和“查找不成功的ASL”
ASL指的是 平均查找時(shí)間
關(guān)鍵字序列:(7、8、30、11、18、9、14)
散列函數(shù):?
H(Key) = (key x 3) MOD 7
裝載因子:?
0.7
處理沖突:線性探測(cè)再散列法
查找成功的ASL計(jì)算方法:
以下求解過程是按照“計(jì)算機(jī)統(tǒng)考的計(jì)算方法”,不同的老師、教材在“處理沖突”上可能會(huì)有不同的方法,所以最主要的是掌握原理即可,對(duì)于考研的朋友最好掌握統(tǒng)考真題的解題方法。?
題目?
例子:(2010年全國(guó)碩士研究生入學(xué)統(tǒng)一考試計(jì)算機(jī)科學(xué)與技術(shù)學(xué)科聯(lián)考計(jì)算機(jī)學(xué)科專業(yè)基礎(chǔ)綜合試題第一題)
將關(guān)鍵字序列(7、8、30、11、18、9、14)散列存儲(chǔ)到散列表中。散列表的存儲(chǔ)空間是一個(gè)下標(biāo)從0開始的一維數(shù)組。散列函數(shù)為: H(key) = (keyx3) MOD 7,處理沖突采用線性探測(cè)再散列法,要求裝填(載)因子為0.7。?
(1) 請(qǐng)畫出所構(gòu)造的散列表;?
(2) 分別計(jì)算等概率情況下查找成功和查找不成功的平均查找長(zhǎng)度。?
1.散列表:?
α = 表中填入的記錄數(shù)/哈希表長(zhǎng)度 ==> 哈希表長(zhǎng)度 = 7/0.7 = 10?
H(7) = (7x3) MOD 7 = 0 H(8) = (8x3) MOD 7 = 3 H(30) = (30x3) MOD 7 = 6?
H(11) = (11x3) MOD 7 = 5 H(18) = (18x3) MOD 7 = 5 H(9) = (9x3) MOD 7 = 6?
H(14) = (14x3) MOD 7 = 0?
按關(guān)鍵字序列順序依次向哈希表中填入,發(fā)生沖突后按照“線性探測(cè)”探測(cè)到第一個(gè)空位置填入。?
因?yàn)楝F(xiàn)在的數(shù)據(jù)是7個(gè),填充因子是0.7。所以數(shù)組大小=7/0.7=10,即寫出來的散列表大小為10,下標(biāo)從0~9。?
第一個(gè)元素7,帶入散列函數(shù),計(jì)算得0。?
第二個(gè)元素8,帶入散列函數(shù),計(jì)算得3。?
第三個(gè)元素30,帶入散列函數(shù),計(jì)算得6。?
第四個(gè)元素11,帶入散列函數(shù),計(jì)算得5。?
第五個(gè)元素18,帶入散列函數(shù),計(jì)算得5;此時(shí)和11沖突,使用線性探測(cè)法,得7。?
第六個(gè)元素9,帶入散列函數(shù),計(jì)算得6;此時(shí)和30沖突,使用線性探測(cè)法,得8。?
第七個(gè)元素14,帶入散列函數(shù),計(jì)算得0;此時(shí)和7沖突,使用線性探測(cè)法,得1。?
所以散列表:
?
地址?? ?0?? ?1?? ?2?? ?3?? ?4?? ?5?? ?6?? ?7?? ?8?? ?9
key?? ?7?? ?14?? ???? ?8?? ???? ?11?? ?30?? ?18?? ?9?? ??
2.查找長(zhǎng)度:?
2.1 查找成功的平均查找長(zhǎng)度?
(待查找的數(shù)字肯定在散列表中才會(huì)查找成功)?
查找數(shù)字A的長(zhǎng)度 = 需要和散列表中的數(shù)比較的次數(shù);?
步驟:?
比如 查找數(shù)字:8?
則 H(8) = (8x3) MOD 7 = 3?
哈希表中地址3處的數(shù)字為8,進(jìn)行了第一次比較:8 = 8,則查找成功,查找長(zhǎng)度為1;?
比如查找數(shù)字:14?
則 H(14) = (14x3) MOD 7 = 0?
哈希表中地址0處的數(shù)字為7,進(jìn)行第一次比較:7≠14?
哈希表中地址1處的數(shù)字為14,進(jìn)行第二次比較:14=14 ,則查找成功,查找長(zhǎng)度為2。?
由此可得到如下數(shù)據(jù):【2016年12月26日修改,多謝@一樓的朋友指正】?
0 1 2 3 4 5 6 7 8 9?
7 14 8 11 30 18 9?
1 2 1 1 1 3 3?
所以總的查找成功的平均查找長(zhǎng)度= (1+1+1+1+3+3+2)/7 = 12/7?
2.2查找不成功的平均查找長(zhǎng)度?
(待查找的數(shù)字肯定不在散列表中)?
【解題的關(guān)鍵之處】根據(jù)哈希函數(shù)地址為MOD7,因此任何一個(gè)數(shù)經(jīng)散列函數(shù)計(jì)算以后的初始地址只可能在0~6的位置?
查找0~6位置查找失敗的查找次數(shù)為:?
地址0,到第一個(gè)關(guān)鍵字為空的地址2需要比較3次,因此查找不成功的次數(shù)為3.?
地址1,到第一個(gè)關(guān)鍵字為空的地址2需要比較2次,因此查找不成功的次數(shù)為2.?
地址2,到第一個(gè)關(guān)鍵字為空的地址2需要比較1次,因此查找不成功的次數(shù)為1.?
地址3,到第一個(gè)關(guān)鍵字為空的地址4需要比較2次,因此查找不成功的次數(shù)為2.?
地址4,到第一個(gè)關(guān)鍵字為空的地址4需要比較1次,因此查找不成功的次數(shù)為1.?
地址5,到第一個(gè)關(guān)鍵字為空的地址2(比較到地址6,再循環(huán)回去)需要比較5次,因此查找不成功的次數(shù)為5.?
地址6,到第一個(gè)關(guān)鍵字為空的地址2(比較到地址6,再循環(huán)回去)需要比較4次,因此查找不成功的次數(shù)為4.?
于是得到如下數(shù)據(jù):?
0 1 2 3 4 5 6 7 8 9?
7 14 8 11 30 18 9?
3 2 1 2 1 5 4?
則查找不成功的平均查找長(zhǎng)度 = (3+2+1+2+1+5+4)/7 = 18/7
二.hash算法原理詳解
一.概念
?
哈希表就是一種以 鍵-值(key-indexed) 存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu),我們只要輸入待查找的值即key,即可查找到其對(duì)應(yīng)的值。
哈希的思路很簡(jiǎn)單,如果所有的鍵都是整數(shù),那么就可以使用一個(gè)簡(jiǎn)單的無序數(shù)組來實(shí)現(xiàn):將鍵作為索引,值即為其對(duì)應(yīng)的值,這樣就可以快速訪問任意鍵的值。這是對(duì)于簡(jiǎn)單的鍵的情況,我們將其擴(kuò)展到可以處理更加復(fù)雜的類型的鍵。
使用哈希查找有兩個(gè)步驟:
1.?使用哈希函數(shù)將被查找的鍵轉(zhuǎn)換為數(shù)組的索引。在理想的情況下,不同的鍵會(huì)被轉(zhuǎn)換為不同的索引值,但是在有些情況下我們需要處理多個(gè)鍵被哈希到同一個(gè)索引值的情況。所以哈希查找的第二個(gè)步驟就是處理沖突
2.?處理哈希碰撞沖突。有很多處理哈希碰撞沖突的方法,本文后面會(huì)介紹拉鏈法和線性探測(cè)法。
哈希表是一個(gè)在時(shí)間和空間上做出權(quán)衡的經(jīng)典例子。如果沒有內(nèi)存限制,那么可以直接將鍵作為數(shù)組的索引。那么所有的查找時(shí)間復(fù)雜度為O(1);如果沒有時(shí)間限制,那么我們可以使用無序數(shù)組并進(jìn)行順序查找,這樣只需要很少的內(nèi)存。哈希表使用了適度的時(shí)間和空間來在這兩個(gè)極端之間找到了平衡。只需要調(diào)整哈希函數(shù)算法即可在時(shí)間和空間上做出取舍。
?
?
在Hash表中,記錄在表中的位置和其關(guān)鍵字之間存在著一種確定的關(guān)系。這樣我們就能預(yù)先知道所查關(guān)鍵字在表中的位置,從而直接通過下標(biāo)找到記錄。使ASL趨近與0.
?
??????????????1)???哈希(Hash)函數(shù)是一個(gè)映象,即:?將關(guān)鍵字的集合映射到某個(gè)地址集合上,它的設(shè)置很靈活,只要這個(gè)地 ??????址集合的大小不超出允許范圍即可;
?????????????2)??由于哈希函數(shù)是一個(gè)壓縮映象,因此,在一般情況下,很容易產(chǎn)生“沖突”現(xiàn)象,即:?key1!=key2,而??f ?(key1) = f(key2)。
??????????????3).??只能盡量減少?zèng)_突而不能完全避免沖突,這是因?yàn)橥ǔjP(guān)鍵字集合比較大,其元素包括所有可能的關(guān)鍵字,?而地址集合的元素僅為哈希表中的地址值
?
???????在構(gòu)造這種特殊的“查找表”?時(shí),除了需要選擇一個(gè)“好”(盡可能少產(chǎn)生沖突)的哈希函數(shù)之外;還需要找到一 種“處理沖突”?的方法。
?
二.Hash構(gòu)造函數(shù)的方法
?
???1.直接定址法:
?????????????????????????
?直接定址法是以數(shù)據(jù)元素關(guān)鍵字k本身或它的線性函數(shù)作為它的哈希地址,即:H(k)=k ?或 H(k)=a×k+b ; (其中a,b為常數(shù))
??例1,有一個(gè)人口統(tǒng)計(jì)表,記錄了從1歲到100歲的人口數(shù)目,其中年齡作為關(guān)鍵字,哈希函數(shù)取關(guān)鍵字本身,如圖(1):
地址
A1
A2
……
A99
A100
年齡
1
2
……
99
100
人數(shù)
980
800
……
495
107
可以看到,當(dāng)需要查找某一年齡的人數(shù)時(shí),直接查找相應(yīng)的項(xiàng)即可。如查找99歲的老人數(shù),則直接讀出第99項(xiàng)即可。
?
地址
A0
A1
……
A99
A100
年齡
1980
1981
……
1999
2000
人數(shù)
980
800
……
495
107
?
如果我們要統(tǒng)計(jì)的是80后出生的人口數(shù),如上表所示,那么我們隊(duì)出生年份這個(gè)關(guān)鍵字可以用年份減去1980來作為地址,此時(shí)f(key)=key-1980
這種哈希函數(shù)簡(jiǎn)單,并且對(duì)于不同的關(guān)鍵字不會(huì)產(chǎn)生沖突,但可以看出這是一種較為特殊的哈希函數(shù),實(shí)際生活中,關(guān)鍵字的元素很少是連續(xù)的。用該方法產(chǎn)生的哈希表會(huì)造成空間大量的浪費(fèi),因此這種方法適應(yīng)性并不強(qiáng)。[2]↑
??此法僅適合于:地址集合的大小?= =?關(guān)鍵字集合的大小,其中a和b為常數(shù)。
?
?
2.數(shù)字分析法:
?????????????假設(shè)關(guān)鍵字集合中的每個(gè)關(guān)鍵字都是由?s?位數(shù)字組成?(u1, u2, …, us),分析關(guān)鍵字集中的全體,并從中提取分布均勻的若干位或它們的組合作為地址。
數(shù)字分析法是取數(shù)據(jù)元素關(guān)鍵字中某些取值較均勻的數(shù)字位作為哈希地址的方法。即當(dāng)關(guān)鍵字的位數(shù)很多時(shí),可以通過對(duì)關(guān)鍵字的各位進(jìn)行分析,丟掉分布不均勻的位,作為哈希值。它只適合于所有關(guān)鍵字值已知的情況。通過分析分布情況把關(guān)鍵字取值區(qū)間轉(zhuǎn)化為一個(gè)較小的關(guān)鍵字取值區(qū)間。
???例2,要構(gòu)造一個(gè)數(shù)據(jù)元素個(gè)數(shù)n=80,哈希長(zhǎng)度m=100的哈希表。不失一般性,我們這里只給出其中8個(gè)關(guān)鍵字進(jìn)行分析,8個(gè)關(guān)鍵字如下所示:
K1=61317602 ?????K2=61326875 ?????K3=62739628 ?????K4=61343634
K5=62706815 ?????K6=62774638 ?????K7=61381262 ?????K8=61394220
分析上述8個(gè)關(guān)鍵字可知,關(guān)鍵字從左到右的第1、2、3、6位取值比較集中,不宜作為哈希地址,剩余的第4、5、7、8位取值較均勻,可選取其中的兩位作為哈希地址。設(shè)選取最后兩位作為哈希地址,則這8個(gè)關(guān)鍵字的哈希地址分別為:2,75,28,34,15,38,62,20。???????????
?
?此法適于:能預(yù)先估計(jì)出全體關(guān)鍵字的每一位上各種數(shù)字出現(xiàn)的頻度。
?????????????
3.折疊法:
????????????將關(guān)鍵字分割成若干部分,然后取它們的疊加和為哈希地址。兩種疊加處理的方法:移位疊加:將分?割后的幾部分低位對(duì)齊相加;邊界疊加:從一端沿分割界來回折疊,然后對(duì)齊相加。
所謂折疊法是將關(guān)鍵字分割成位數(shù)相同的幾部分(最后一部分的位數(shù)可以不同),然后取這幾部分的疊加和(舍去進(jìn)位),這方法稱為折疊法。這種方法適用于關(guān)鍵字位數(shù)較多,而且關(guān)鍵字中每一位上數(shù)字分布大致均勻的情況。
??折疊法中數(shù)位折疊又分為移位疊加和邊界疊加兩種方法,移位疊加是將分割后是每一部分的最低位對(duì)齊,然后相加;邊界疊加是從一端向另一端沿分割界來回折疊,然后對(duì)齊相加。
例4,當(dāng)哈希表長(zhǎng)為1000時(shí),關(guān)鍵字key=110108331119891,允許的地址空間為三位十進(jìn)制數(shù),則這兩種疊加情況如圖:
???????移位疊加 ????????????????????????????????邊界疊加
???????8 9 1 ????????????????????????????????????8 9 1
???????1 1 9 ????????????????????????????????????9 1 1
???????3 3 1 ????????????????????????????????????3 3 1
???????1 0 8 ????????????????????????????????????8 0 1
????+ ?1 1 0 ??????????????????????????????????+ 1 1 0 ?????????????
???(1) 5 5 9 ?????????????????????????????????(3)0 4 4
?????????????????圖(2)由折疊法求哈希地址
?????用移位疊加得到的哈希地址是559,而用邊界疊加所得到的哈希地址是44。如果關(guān)鍵字不是數(shù)值而是字符串,則可先轉(zhuǎn)化為數(shù)。轉(zhuǎn)化的辦法可以用ASCⅡ字符或字符的次序值。
????????????此法適于:關(guān)鍵字的數(shù)字位數(shù)特別多。
?
4.平方取中法
??這是一種常用的哈希函數(shù)構(gòu)造方法。這個(gè)方法是先取關(guān)鍵字的平方,然后根據(jù)可使用空間的大小,選取平方數(shù)是中間幾位為哈希地址。
哈希函數(shù) H(key)=“key2的中間幾位”因?yàn)檫@種方法的原理是通過取平方擴(kuò)大差別,平方值的中間幾位和這個(gè)數(shù)的每一位都相關(guān),則對(duì)不同的關(guān)鍵字得到的哈希函數(shù)值不易產(chǎn)生沖突,由此產(chǎn)生的哈希地址也較為均勻。
例5,若設(shè)哈希表長(zhǎng)為1000則可取關(guān)鍵字平方值的中間三位,如圖所示:
關(guān)鍵字
關(guān)鍵字的平方
哈希函數(shù)值
1234
1522756
227
2143
4592449
924
4132
17073424
734
3214
10329796
297?
??
下面給出平方取中法的哈希函數(shù)
?????//平方取中法哈希函數(shù),結(jié)設(shè)關(guān)鍵字值32位的整數(shù)
?????//哈希函數(shù)將返回key * key的中間10位
???????Int ?Hash (int key)
?????????{
?????//計(jì)算key的平方
??????Key * = key ;
?????//去掉低11位
?????Key>>=11;
?????// 返回低10位(即key * key的中間10位)
???????Return key %1024;
??????????}
???此法適于:關(guān)鍵字中的每一位都有某些數(shù)字重復(fù)出現(xiàn)頻度很高的現(xiàn)象
?
?
5.減去法
?
?
減去法是數(shù)據(jù)的鍵值減去一個(gè)特定的數(shù)值以求得數(shù)據(jù)存儲(chǔ)的位置。
例7,公司有一百個(gè)員工,而員工的編號(hào)介于1001到1100,減去法就是員工編號(hào)減去1000后即為數(shù)據(jù)的位置。編號(hào)1001員工的數(shù)據(jù)在數(shù)據(jù)中的第一筆。編號(hào)1002員工的數(shù)據(jù)在數(shù)據(jù)中的第二筆…依次類推。從而獲得有關(guān)員工的所有信息,因?yàn)榫幪?hào)1000以前并沒有數(shù)據(jù),所有員工編號(hào)都從1001開始編號(hào)。
?
?
6.基數(shù)轉(zhuǎn)換法
??將十進(jìn)制數(shù)X看作其他進(jìn)制,比如十三進(jìn)制,再按照十三進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制數(shù),提取其中若干為作為X的哈希值。一般取大于原來基數(shù)的數(shù)作為轉(zhuǎn)換的基數(shù),并且兩個(gè)基數(shù)應(yīng)該是互素的。
?
例Hash(80127429)=(80127429)13=8*137+0*136+1*135+2*134+7*133+4*132+2*131+9=(502432641)10如果取中間三位作為哈希值,得Hash(80127429)=432
?為了獲得良好的哈希函數(shù),可以將幾種方法聯(lián)合起來使用,比如先變基,再折疊或平方取中等等,只要散列均勻,就可以隨意拼湊。
?
?
?
??7.除留余數(shù)法:
????????????
假設(shè)哈希表長(zhǎng)為m,p為小于等于m的最大素?cái)?shù),則哈希函數(shù)為
h(k)=k??%??p?,其中%為模p取余運(yùn)算。
例如,已知待散列元素為(18,75,60,43,54,90,46),表長(zhǎng)m=10,p=7,則有
????h(18)=18 % 7=4????h(75)=75 % 7=5????h(60)=60 % 7=4???
????h(43)=43 % 7=1????h(54)=54 % 7=5????h(90)=90 % 7=6???
????h(46)=46 % 7=4
此時(shí)沖突較多。為減少?zèng)_突,可取較大的m值和p值,如m=p=13,結(jié)果如下:
????h(18)=18 % 13=5????h(75)=75 % 13=10????h(60)=60 % 13=8 ???
????h(43)=43 % 13=4????h(54)=54 % 13=2????h(90)=90 % 13=12???
????h(46)=46 % 13=7
此時(shí)沒有沖突,如圖8.25所示。
?
0??????1??????2?????3?????4?????5??????6?????7?????8?????9?????10?????11????12
?
?
?
54
?
43
18
?
46
60
?
75
?
90
??????????????????????
?
除留余數(shù)法求哈希地址
?
?
理論研究表明,除留余數(shù)法的模p取不大于表長(zhǎng)且最接近表長(zhǎng)m素?cái)?shù)時(shí)效果最好,且p最好取1.1n~1.7n之間的一個(gè)素?cái)?shù)(n為存在的數(shù)據(jù)元素個(gè)數(shù))
?
?
8.隨機(jī)數(shù)法:
???????????設(shè)定哈希函數(shù)為:H(key) = Random(key)其中,Random?為偽隨機(jī)函數(shù)
???????????此法適于:對(duì)長(zhǎng)度不等的關(guān)鍵字構(gòu)造哈希函數(shù)。
?
?????????實(shí)際造表時(shí),采用何種構(gòu)造哈希函數(shù)的方法取決于建表的關(guān)鍵字集合的情況(包括關(guān)鍵字的范圍和形態(tài)),以及哈希表 ???長(zhǎng)度(哈希地址范圍),總的原則是使產(chǎn)生沖突的可能性降到盡可能地小。
?
9.隨機(jī)乘數(shù)法
??亦稱為“乘余取整法”。隨機(jī)乘數(shù)法使用一個(gè)隨機(jī)實(shí)數(shù)f,0≤f<1,乘積f*k的分?jǐn)?shù)部分在0~1之間,用這個(gè)分?jǐn)?shù)部分的值與n(哈希表的長(zhǎng)度)相乘,乘積的整數(shù)部分就是對(duì)應(yīng)的哈希值,顯然這個(gè)哈希值落在0~n-1之間。其表達(dá)公式為:Hash(k)=「n*(f*k%1)」其中“f*k%1”表示f*k 的小數(shù)部分,即f*k%1=f*k-「f*k」
??例10,對(duì)下列關(guān)鍵字值集合采用隨機(jī)乘數(shù)法計(jì)算哈希值,隨機(jī)數(shù)f=0.103149002 哈希表長(zhǎng)度n=100得圖:
?
k
f*k
n*((f*k)的小數(shù)部分)
Hash(k)
319426
32948.47311
47.78411
47
718309
74092.85648
86.50448
86
629443
64926.41727
42.14427
42
919697
84865.82769
83.59669
83
??此方法的優(yōu)點(diǎn)是對(duì)n的選擇不很關(guān)鍵。通常若地址空間為p位就是選n=2p.Knuth對(duì)常數(shù)f的取法做了仔細(xì)的研究,他認(rèn)為f取任何值都可以,但某些值效果更好。如f=(-1)/2=0.6180329...比較理想。
?
10.字符串?dāng)?shù)值哈希法
在很都情況下關(guān)鍵字是字符串,因此這樣對(duì)字符串設(shè)計(jì)Hash函數(shù)是一個(gè)需要討論的問題。下列函數(shù)是取字符串前10個(gè)字符來設(shè)計(jì)的哈希函數(shù)
Int Hash _ char (char *X)
{
??int I?,sum
??i=0;
??while (i 10 && X[i])
??Sum +=X[i++];
??sum%=N; ?????//N是記錄的條數(shù)
??}
這種函數(shù)把字符串的前10個(gè)字符的ASCⅡ值之和對(duì)N取摸作為Hash地址,只要N較小,Hash地址將較均勻分布[0,N]區(qū)間內(nèi),因此這個(gè)函數(shù)還是可用的。對(duì)于N很大的情形,可使用下列函數(shù)
int ELFhash (char *key )
{
?Unsigned long h=0,g;
whie (*key)
{
h=(h<<4)+ *key;
key++;
g=h & 0 xF0000000L;
if (g) h^=g>>24;
h & =~g;
}
h=h % N
return (h);
}
??這個(gè)函數(shù)稱為ELFHash(Exextable and Linking Format ,ELF,可執(zhí)行鏈接格式)函數(shù)。它把一個(gè)字符串的絕對(duì)長(zhǎng)度作為輸入,并通過一種方式把字符的十進(jìn)制值結(jié)合起來,對(duì)長(zhǎng)字符串和短字符串都有效,這種方式產(chǎn)生的位置不可能不均勻分布。
?
11.旋轉(zhuǎn)法
??旋轉(zhuǎn)法是將數(shù)據(jù)的鍵值中進(jìn)行旋轉(zhuǎn)。旋轉(zhuǎn)法通常并不直接使用在哈希函數(shù)上,而是搭配其他哈希函數(shù)使用。
??例11,某學(xué)校同一個(gè)系的新生(小于100人)的學(xué)號(hào)前5位數(shù)是相同的,只有最后2位數(shù)不同,我們將最后一位數(shù),旋轉(zhuǎn)放置到第一位,其余的往右移。
新生學(xué)號(hào)
旋轉(zhuǎn)過程
旋轉(zhuǎn)后的新鍵值
5062101
5062101
1506210
5062102
5062102
2506210
5062103
5062103
3506210
5062104
5062104
4506210
5062105
5062105
5506210
????????????????????如圖
?運(yùn)用這種方法可以只輸入一個(gè)數(shù)值從而快速地查到有關(guān)學(xué)生的信息。
?
?
在實(shí)際應(yīng)用中,應(yīng)根據(jù)具體情況,靈活采用不同的方法,并用實(shí)際數(shù)據(jù)測(cè)試它的性能,以便做出正確判定。通常應(yīng)考慮以下五個(gè)因素?:
l?計(jì)算哈希函數(shù)所需時(shí)間?(簡(jiǎn)單)。
l?關(guān)鍵字的長(zhǎng)度。
l?哈希表大小。
l?關(guān)鍵字分布情況。
l?記錄查找頻率
?
?
?
三.Hash處理沖突方法
?
???通過構(gòu)造性能良好的哈希函數(shù),可以減少?zèng)_突,但一般不可能完全避免沖突,因此解決沖突是哈希法的另一個(gè)關(guān)鍵問題。創(chuàng)建哈希表和查找哈希表都會(huì)遇到?jīng)_突,兩種情況下解決沖突的方法應(yīng)該一致。下面以創(chuàng)建哈希表為例,說明解決沖突的方法。常用的解決沖突方法有以下四種:
?
?通過構(gòu)造性能良好的哈希函數(shù),可以減少?zèng)_突,但一般不可能完全避免沖突,因此解決沖突是哈希法的另一個(gè)關(guān)鍵問題。創(chuàng)建哈希表和查找哈希表都會(huì)遇到?jīng)_突,兩種情況下解決沖突的方法應(yīng)該一致。下面以創(chuàng)建哈希表為例,說明解決沖突的方法。常用的解決沖突方法有以下四種:
1.?????????開放定址法
這種方法也稱再散列法,其基本思想是:當(dāng)關(guān)鍵字key的哈希地址p=H(key)出現(xiàn)沖突時(shí),以p為基礎(chǔ),產(chǎn)生另一個(gè)哈希地址p1,如果p1仍然沖突,再以p為基礎(chǔ),產(chǎn)生另一個(gè)哈希地址p2,…,直到找出一個(gè)不沖突的哈希地址pi?,將相應(yīng)元素存入其中。這種方法有一個(gè)通用的再散列函數(shù)形式:
??????????Hi=(H(key)+di)% m???i=1,2,…,n
????其中H(key)為哈希函數(shù),m?為表長(zhǎng),di稱為增量序列。增量序列的取值方式不同,相應(yīng)的再散列方式也不同。主要有以下三種:
l?????????線性探測(cè)再散列
????dii=1,2,3,…,m-1
這種方法的特點(diǎn)是:沖突發(fā)生時(shí),順序查看表中下一單元,直到找出一個(gè)空單元或查遍全表。
l?????????二次探測(cè)再散列
????di=12,-12,22,-22,…,k2,-k2????( k<=m/2 )
????這種方法的特點(diǎn)是:沖突發(fā)生時(shí),在表的左右進(jìn)行跳躍式探測(cè),比較靈活。
l?????????偽隨機(jī)探測(cè)再散列
????di=偽隨機(jī)數(shù)序列。
具體實(shí)現(xiàn)時(shí),應(yīng)建立一個(gè)偽隨機(jī)數(shù)發(fā)生器,(如i=(i+p) % m),并給定一個(gè)隨機(jī)數(shù)做起點(diǎn)。
例如,已知哈希表長(zhǎng)度m=11,哈希函數(shù)為:H(key)= key??%??11,則H(47)=3,H(26)=4,H(60)=5,假設(shè)下一個(gè)關(guān)鍵字為69,則H(69)=3,與47沖突。如果用線性探測(cè)再散列處理沖突,下一個(gè)哈希地址為H1=(3 + 1)% 11 = 4,仍然沖突,再找下一個(gè)哈希地址為H2=(3 + 2)% 11 = 5,還是沖突,繼續(xù)找下一個(gè)哈希地址為H3=(3 + 3)% 11 = 6,此時(shí)不再?zèng)_突,將69填入5號(hào)單元,參圖8.26 (a)。如果用二次探測(cè)再散列處理沖突,下一個(gè)哈希地址為H1=(3 + 12)% 11 = 4,仍然沖突,再找下一個(gè)哈希地址為H2=(3 - 12)% 11 = 2,此時(shí)不再?zèng)_突,將69填入2號(hào)單元,參圖8.26 (b)。如果用偽隨機(jī)探測(cè)再散列處理沖突,且偽隨機(jī)數(shù)序列為:2,5,9,……..,則下一個(gè)哈希地址為H1=(3 + 2)% 11 = 5,仍然沖突,再找下一個(gè)哈希地址為H2=(3 + 5)% 11 = 8,此時(shí)不再?zèng)_突,將69填入8號(hào)單元,參圖8.26 (c)。
?
?
0????????1???????2??????3??????4??????5???????6??????7??????8???????9??????10????
?
?
?
?
47
26
60
69
?
?
?
?
?????????(a)?用線性探測(cè)再散列處理沖突
?
?
0????????1???????2??????3??????4??????5???????6??????7??????8???????9??????10????
?
?
?
69
47
26
60
?
?
?
?
?
?????????(b)?用二次探測(cè)再散列處理沖突
?
?
0????????1???????2??????3??????4??????5???????6??????7??????8???????9??????10????
?
?
?
?
47
26
60
?
?
69
?
?
?????????(c)?用偽隨機(jī)探測(cè)再散列處理沖突
?
??????????????????????圖8.26開放地址法處理沖突
從上述例子可以看出,線性探測(cè)再散列容易產(chǎn)生“二次聚集”,即在處理同義詞的沖突時(shí)又導(dǎo)致非同義詞的沖突。例如,當(dāng)表中i, i+1 ,i+2三個(gè)單元已滿時(shí),下一個(gè)哈希地址為i,?或i+1 ,或i+2,或i+3的元素,都將填入i+3這同一個(gè)單元,而這四個(gè)元素并非同義詞。線性探測(cè)再散列的優(yōu)點(diǎn)是:只要哈希表不滿,就一定能找到一個(gè)不沖突的哈希地址,而二次探測(cè)再散列和偽隨機(jī)探測(cè)再散列則不一定。
?
2.?再哈希法
????這種方法是同時(shí)構(gòu)造多個(gè)不同的哈希函數(shù):
????Hi=RH1(key)??i=1,2,…,k
當(dāng)哈希地址Hi=RH1(key)發(fā)生沖突時(shí),再計(jì)算Hi=RH2(key)……,直到?jīng)_突不再產(chǎn)生。這種方法不易產(chǎn)生聚集,但增加了計(jì)算時(shí)間。
3.?鏈地址法
????這種方法的基本思想是將所有哈希地址為i的元素構(gòu)成一個(gè)稱為同義詞鏈的單鏈表,并將單鏈表的頭指針存在哈希表的第i個(gè)單元中,因而查找、插入和刪除主要在同義詞鏈中進(jìn)行。鏈地址法適用于經(jīng)常進(jìn)行插入和刪除的情況。
例如,已知一組關(guān)鍵字(32,40,36,53,16,46,71,27,42,24,49,64),哈希表長(zhǎng)度為13,哈希函數(shù)為:H(key)= key % 13,則用鏈地址法處理沖突的結(jié)果如圖
?
?
??? ?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
圖鏈地址法處理沖突時(shí)的哈希表
本例的平均查找長(zhǎng)度?ASL=(1*7+2*4+3*1)=1.5
4.建立公共溢出區(qū)
這種方法的基本思想是:將哈希表分為基本表和溢出表兩部分,凡是和基本表發(fā)生沖突的元素,一律填入溢出表
?
?
參考資料
大話數(shù)據(jù)結(jié)
算法導(dǎo)論
---------------------
作者:creator123123?
原文:https://blog.csdn.net/creator123123/article/details/81572288?
?
總結(jié)
以上是生活随笔為你收集整理的hash函数查找和ASL计算的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于数据库主键和外键
- 下一篇: 强制进程结束(内核函数)