Remove ads
来自维基百科,自由的百科全书
雜湊表(Hash table),是根據鍵(Key)而直接查詢在記憶體儲存位置的資料結構。也就是說,它通過計算出一個鍵值的函式,將所需查詢的資料對映到表中一個位置來讓人查詢,這加快了尋找速度。這個對映函式稱做雜湊函式,存放記錄的陣列稱做雜湊表。
一個通俗的例子是,為了尋找電話簿中某人的號碼,可以建立一個按照人名首字母順序排列的表(即建立人名到首字母的一個函式關係),在首字母為W的表中尋找「王」姓的電話號碼,顯然比直接尋找就要快得多。這裡使用人名作為關鍵字,「取首字母」是這個例子中雜湊函式的函式法則,存放首字母的表對應雜湊表。關鍵字和函式法則理論上可以任意確定。
可以將雜湊表理解為一串按順序放的陣列,陣列的下標是從key經過計算得出,陣列每個位置存放 value。這裡有很多將key轉換為下標的函式,比如取模,md5等。可以在雜湊表視覺化頁面 直觀操作,理解這裡的資料結構。
雜湊函式能使對一個資料序列的查詢過程更加迅速有效,通過雜湊函式,資料元素將被更快定位。
為了知道衝突產生的相同雜湊函式位址所對應的關鍵字,必須選用另外的雜湊函式,或者對衝突結果進行處理。而不發生衝突的可能性是非常之小的,所以通常對衝突進行處理。常用方法有以下幾種:
顯示線性探測填裝一個雜湊表的過程:
雜湊位址 | 空表 | 插入89 | 插入18 | 插入49 | 插入58 | 插入69 |
---|---|---|---|---|---|---|
0 | 49 | 49 | 49 | |||
1 | 58 | 58 | ||||
2 | 69 | |||||
3 | ||||||
4 | ||||||
5 | ||||||
6 | ||||||
7 | ||||||
8 | 18 | 18 | 18 | 18 | ||
9 | 89 | 89 | 89 | 89 | 89 |
聚集(Cluster,也翻譯做「堆積」)的意思是,在函式位址的表中,雜湊函式的結果不均勻地占據表的單元,形成區塊,造成線性探測產生一次聚集(primary clustering)和平方探測的二次聚集(secondary clustering),雜湊到區塊中的任何關鍵字需要尋找多次試選單元才能插入表中,解決衝突,造成時間浪費。對於開放定址法,聚集會造成效能的災難性損失,是必須避免的。
尋找空單元並插入:
雜湊表的尋找過程基本上和造表過程相同。一些關鍵碼可通過雜湊函式轉換的位址直接找到,另一些關鍵碼在雜湊函式得到的位址上產生了衝突,需要按處理衝突的方法進行尋找。在介紹的三種處理衝突的方法中,產生衝突後的尋找仍然是給定值與關鍵碼進行比較的過程。所以,對雜湊表尋找效率的量度,依然用平均尋找長度來衡量。
尋找過程中,關鍵碼的比較次數,取決於產生衝突的多少,產生的衝突少,尋找效率就高,產生的衝突多,尋找效率就低。因此,影響產生衝突多少的因素,也就是影響尋找效率的因素。影響產生衝突多少有以下三個因素:
雜湊表的載荷因子定義為: = 填入表中的元素個數 / 雜湊表的長度
是雜湊表裝滿程度的標誌因子。由於表長是定值,與「填入表中的元素個數」成正比,所以,越大,表明填入表中的元素越多,產生衝突的可能性就越大;反之,越小,標明填入表中的元素越少,產生衝突的可能性就越小。實際上,雜湊表的平均尋找長度是載荷因子的函式,只是不同處理衝突的方法有不同的函式。
對於開放定址法,荷載因子是特別重要因素,應嚴格限制在0.7-0.8以下。超過0.8,查表時的CPU快取不命中(cache missing)按照指數曲線上升。因此,一些採用開放定址法的hash庫,如Java的系統庫限制了荷載因子為0.75,超過此值將resize雜湊表。
Linux作業系統在物理檔案系統與塊裝置驅動程式之間引入了「緩衝區快取」(Buffer
Cache,簡稱bcache)。當讀寫磁碟檔案的資料,實際上都是對bcache操作,這大大提高了讀寫資料的速度。如果要讀寫的磁碟資料不在bcache中,即快取不命中(miss),則把相應資料從磁碟載入到bcache中。一個快取資料大小是與檔案系統上一個邏輯塊的大小相對應的(例如1KiB位元組),在bcache中每個快取資料塊用struct buffer_head
記載其元資訊:
整個bcache以struct buffer_head
為基本資料單元,組織為一個封閉定址(close addressing,即「單獨鏈結串列法」解決衝突)的雜湊表struct buffer_head * hash_table[NR_HASH];
雜湊函式的輸入關鍵字是b_blocknr(邏輯塊號)與b_dev(裝置號)。計算hash值的雜湊函式表達式為:
其中NR_HASH是雜湊表的條目總數。發生「 衝突」的struct buffer_head
,以b_prev與b_next指標組成一個雙向(不迴圈)鏈結串列。bcache中所有的struct buffer_head
,包括使用中不空閒與未使用空閒的struct buffer_head
,以b_prev_free和b_next_free指標組成一個雙向迴圈鏈結串列free_list,其中未使用空閒的struct buffer_head
放在該鏈結串列的前部。
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.