處理沖突的方法可以分為兩大類:開放地址法和鏈地址法
開發地址法
開放地址法的基本思想是:把記錄都存儲在散列表數組中,當某一記錄關鍵字key的初始散列地址H0=H(key)發生沖突時,以H0為基礎,采取合適方法計算得到另一個地址H1,如果H1仍然發生沖突 ,以H1為基礎再求下一個地址H2,若H2仍然沖突,再求H3.依次類推,直至Hk不發生沖突為止,則Hk為記錄在表中的散列地址。
這種方法在尋找“下一個”空的散列地址時,原來的數組空間對所有的元素都是開放的,所以稱為開放地址法。通常把尋找“下一個”空位的過程稱為探測,上述方法可用如下公式表示
Hi=(H(key)+di)%m i=1,2,...,k (k<=m-1)
其中,H(key)為散列函數,m為散列表表長,di為增量序列。根據di取值的不同,可以分為以下三種探測方法:
(1)線性探測法:
di=1,2,3,。。。,m-1
這種探測方法可以將散列表假想成一個循環表,發生沖突時,從沖突地址的下一個單元順序尋找空單元,如果到最后一個位置也沒有找到空單元,則回到表頭開始繼續查找 ,直到找到一個空位,就把此元素放入空位中,如果找不到空位,則說明散列表已滿,需要進行溢出處理。
(2)二次探測法
di=1^2, -1^2, 2^2, -2^2,...,+k^2 ,-k^2(k<=m/2)
(3)偽隨機探測法
di=偽隨機數序列
例如,散列表的長度為11,散列函數H(key)=key%11,假設表中已填有關鍵字分別為17、60、29的記錄,現在有第四個記錄,其關鍵字為38,由散列函數得到散列地址為5,產生沖突。
若用線性探測法處理時,得到下一個地址6,仍沖突;再求下一個地址7,仍沖突直到散列地址為 8的位置為“空”時為止,處理沖突的過程結束,38填入散列表中序號為 8的 位置。
若用二次探測法,散列地址5沖突后,得到下一個地址6,仍沖突;再求得到下一個地址4,無沖突,38填入序號為4的 位置。
若用偽隨機探測法,假設產生的偽隨機數為9,則計算下一個散列地址為(5+9)%11=3,所以38填入序號為3的位置。
從上述線性探測法處理的過程中可以看到一個現象:當表中 i,i+1,i+2位置上已填有記錄時,下一個散列地址為i、i+1、i+2和i+3的記錄都將填入i+3的位置,這種在處理沖突過程中發生的兩個第一散列地址不同的記錄爭奪同一個后續散列地址的現象稱作“二次聚集(或稱作“堆積”)”即在處理同義詞的沖突過程中又添加了非同義詞的沖突。
可以看出,上述三種處理方法各有優缺點。線性探測法的優點是:只要散列表未填滿,總能找到一個不發生沖突的地址:缺點是:會產生“二次聚集”現象。而二次聚集探測法和偽隨機探測法的優點是:可以避免“二次聚集”現象;缺點也很顯然:不能保證一定找到不發生沖突的地址。
鏈地址法
鏈地址的基本思想是:把具有相同散列地址的記錄放在同一個單鏈表中,稱為同義詞鏈表。有m個散列地址就有m個單鏈表,同時用數組HT[0...m-1]存放各個鏈表的頭指針,凡是散列地址為i的記錄都以結點插入到HT[i]為頭結點的單鏈表中。