之所以會接觸到雜湊,是因為在學習中遇到這麼乙個問題:「根據課堂中所介紹的雜湊索引原理,實現乙個自增長雜湊索引的原型。」
那麼就根據上面這個問題,來**下關於雜湊的一些基礎知識。
這裡說下傳統的查詢操作,設計如下場景:
角色:班主任、校長、學生
需求:找學生中的「張三」
那麼場景1:校長要找「張三」,笨的一種方式,是獲取學生名單,然後進行比對,發現「張三」,則找人成功。
場景2:還是校長找「張三」,通過班主任找,班主任可以直接找到自己的學生「張三」,則找人成功。
這裡的場景1與場景2,則是傳統的查詢操作與「雜湊」的對比:
傳統查詢通過給定的key,通過比對獲取相應的value,這個比對的過程是不可省略的。
雜湊查詢,則是通過某種關係f,直接找到相應的key對應的value,其中沒有比對的過程,因此效率非常高。
那麼給出乙個雜湊的小概念:儲存位置 = f( key ),同時我們稱這個關係f為雜湊函式,又稱雜湊函式。
雜湊牛在:我們通過查詢關鍵字,不需要比較就可以獲得需要記錄的儲存位置。這個也稱之為雜湊技術。
下面為雜湊技術與雜湊表做乙個簡單的定義:
"雜湊技術是在記錄的儲存位置和它的關鍵字之間建立乙個確定的對應關係f,使得每個關鍵字key對應乙個儲存位置f ( key )"
查詢時,根據這個確定的對應關係找到給定值key的對映f(key),若查詢集合中存在這個記錄,則必定在f(key)的位置上。
按這個思想,採用雜湊技術將記錄儲存在一塊連續的儲存空間中,這塊連續儲存空間稱為雜湊表或雜湊表(hashtable)。那麼關鍵字對應的記錄儲存位置稱為雜湊位址。
雜湊的過程分為兩步:
1.在儲存的時候,通過雜湊函式計算記錄的雜湊位址,並按此雜湊位址儲存該記錄
2.當查詢記錄時,我們通過同樣的雜湊函式計算記錄的雜湊位址,按此雜湊位址訪問該記錄。
通過這些分析,可以發現雜湊與通用的儲存結構如線性表、樹等區別是:通用資料結構之間元素與元素之間會存在某種邏輯關係,而雜湊的記錄之間不存在邏輯關係,每條記錄只與關鍵字有關。因此,雜湊主要是面向查詢的。
雜湊技術的特長在於:查詢與給定key相符的記錄。(簡化了比較過程,效率提公升)
雜湊的劣勢則在於 :1th. 查詢一對多的關係,如對班級學生做雜湊後,以性別為key,進行查詢,是不合適的
2th. 範圍查詢、最大值、最小值這種具有比較性質的操作,雜湊也是無從計算的。
雜湊演算法有乙個嚴重的問題,就是當key1 ≠ key2,但卻有 f ( key1 ) = f ( key2 );當這種情況發生時,我們稱之為衝突(collision),並把key1和key2稱為這個雜湊函式的同義詞(synonym)
通常解決雜湊衝突的辦法有:1. 開放定址法(open addressing)
2. 拉鍊法(chaining)
對於開放定址有如下幾種方式:
線性探測法公式:fi ( key ) = ( f ( key ) + di ) mod m ( di = 1, 2, 3, ......, m - 1 )
假設有關鍵字集合:
採用的雜湊函式 f ( key ) = key mod 12
下面進行雜湊操作:
f ( 12 ) = 12 mod 12 ----> 0
f ( 67 ) = 67 mod 12 ----> 7
f ( 56 ) = 56 mod 12 ----> 8
f ( 16 ) = 16 mod 12 ----> 4
f ( 25 ) = 25 mod 12 ----> 1
此時的儲存狀態為:
當繼續進行計算 f ( 37 ) = 37 mod 12 ----> 1,此時與25所在的位置發生了衝突,於是應用上面的公式
f ( 37 ) = ( f ( 37 ) + 1 ) mod 12 = ( 1 + 1 ) mod 12 ----> 2。於是將37插入位址為2的位置:
隨後的22, 29, 15, 47均正常插入
當插入48時,f ( 48 ) = 48 mod 12 ----> 0,與12的位置發生衝突,依舊採用上述公式,不過這次當di = 6時,才解決衝突 :
可以看出,解決衝突時,會出現48和37這種不是同義詞卻會爭奪同乙個位址的情況,稱這種情況為堆積。堆積的出現,會使我們不斷的處理衝突,無論是插入還是查詢效率都會變低。
二次探測法公式:fi ( key ) = ( f ( key ) + di ) mod m ( di = 1^2, -1^2, 2^2, -2^2, ......, q^2, -q^2 q <= m / 2 )
二次探測法思路:以雙向的形式,尋找可能的空位置;另外增加平方運算是為了不讓關鍵字都聚集在某一區域
隨機探測法公式:fi ( key ) = ( f ( key ) + di ) mod m ( di是乙個偽隨機數列 )
拉鍊法的思想是當發生衝突時,將所有關鍵字為同義詞的記錄儲存在乙個單鏈表中,我們稱這種表為同義詞子表,而雜湊表中只儲存所有同義詞子表的頭指標(每個子表可以理解為乙個bucket,而雜湊表可以為乙個content)。
還是對上述的關鍵字通過拉鍊法進行雜湊,依舊mod 12:
拉鍊法思路:將所有關鍵字為同義詞的結點鏈結在同乙個單鏈表中。若選定的雜湊表長度為m,則可將雜湊表定義為乙個由m個頭指標組成的指標陣列t[0..m-1]。凡是雜湊位址為i的節點,均插入到以t[i]為頭指標的單鏈表中。t中個分量的初值均應為空指標。
注意:這裡的單鏈表並沒有進行長度限制,這是不合理的,通常會規定乙個閥值,當超過閥值的時候,會將這個單鏈表(也可稱為bucket)進行**處理。如果從時間複雜度的角度考慮,當存在m個單鏈表,尋找到確定的單鏈表的時間複雜度為o(1)(只進行了一次雜湊),當從單鏈表進行元素匹配時的最壞時間複雜度將為o(n)(n為元素個數)。這在某些場景下是不允許的。涉及到的**,將是動態hash了,會下後續的文章中討論,並介紹幾種實現。
陣列:查詢容易,刪除難
鍊錶:查詢難,刪除容易
本次介紹了一些雜湊的基本概念,包括雜湊的定義,雜湊的優勢、劣勢等,在隨後篇幅中將會對雜湊的實現、動態雜湊的實現,雜湊的應用場景加以描述!
現代魔法學院:
一些基礎概念的總結。。。。
寫程式如寫作文?先學語法,學三種流程結構。就相當於寫作文之前學字,句子。但是只會字和句子寫不了作文。想寫東西,有想法。寫程式也是要先要有想法,有了想法才能寫下去。分析為王 物件導向問題分析 分析步驟 找物件 找物件的變數和方法 狀態和行為 通過分析物件中相同的變數和方法,抽象出類 找類和類之間的關係...
PCB的一些基礎概念
1.什麼是pcb?pcb printed circuit board 中文名稱為印製電路板,又稱印刷線路板,是重要的電子部件,是電子元器件的支撐體,是電子元器件電氣連線的載體。由於它是採用電子印刷術製作的,故被稱為 印刷 電路板。2.元器件的分類 插裝 組裝到印製板上時需要在印製板上打通孔,引腳在電...
C 的一些基礎概念
cpp中有預編譯指令 include其中iostream提供乙個命名空間的東西,標準命名空間是std c 中輸入輸出不能直接寫出以下形式 cin a cout a endl 別忘了要事先宣告命名空間中的變數!方式一 std cin a std cout a std endl using std co...