以下均為個人的學習筆記。寫出來是為了在寫的過程中看看自己的想法有沒有什麼毛病。如果您找到了什麼問題,請務必告知我,謝謝!
學習過程完全參照了黑皮書《資料結構與演算法分析》,所以實現**大致與書中一樣(也有些許改動,因為我的黑皮書是c語言實現,而我實際實現所用卻是c++,多少有一些不必要的不同啦),或許現在已經有更好的寫法了,所以僅供參考吧。
先貼出完全的**,再進行逐步分析:
#includeusing namespace std;
//----------------------------//
struct hashtbl;
typedef struct hashtbl* hashtable;//表指標hashtable
struct hashentry;
typedef unsigned int index;
typedef index position;
typedef struct hashentry cell;
enum kindofentry ;//用以標記單元格當前狀態
#define mintablesize 2//最低表尺寸
struct hashentry
;struct hashtbl
;position find(int key, hashtable h);
void insert(int key, hashtable h);
hashtable initializetable(int tablesize);
//----------------------------//
hashtable initializetable(int tablesize)
else
return h; }}
position find(int key, hashtable h)
return currentpos;
}void insert(int key,hashtable h)
}
線性探測:
當發生碰撞的時候,就往下乙個單元格去存放(如果還碰撞就繼續往下,碰到底了就繞回表頭繼續往下)。相對的樸素的一種方法,只要表還沒裝滿,那就一定能給關鍵字找到合適的位置。當然,這也同時很不效率,因為它必須乙個個去匹配判斷,一次次去繞,怎麼想都不是很效率,所以還有另外一種「平方」。
平方探測:
因為上一種不太效率,所以平方探測可能更平常一些。簡單來說,當傳送了碰撞,就去找當前單元格下的 i^2 格,以此類推(其中,i是乙個從1開始的常數,每次判斷都會+1。所以偏移量是按照1,4,9,16的順序來增加的)。
注:還有另外一種平方探測,和上面的相近,只是變成了 (-1)^i(i)^2 而已,並且常量i是每兩回合+1(-1,+1,-4,+4像這樣)。
這種方式能很好的防止過多次數的匹配,因為插入資料的單元都很分散,但也同樣有些毛病。比方說,必須要保證雜湊表足夠大。試想一下,這種匹配方式,是不是有可能導致某個資料來回匹配無數次都沒辦法放進空的單元格裡?解決這種方式就需要讓雜湊表足夠大。顯然,這可能會浪費不少空間,但速度無疑提公升了。
首先是建立表函式:
hashtable initializetable(int tablesize)
}
並不複雜,連**都每幾行。
首先,建立乙個「表指標h」,然後根據輸入的「表尺寸tablesize」建表。
①先為h開闢乙個「表空間」
②尺寸賦予
③為該空間中的「表單元指標」開闢出乙個陣列,以存放每個表單元的資料(我自己偶爾會繞進去,所以姑且打個注釋吧。指標在定義的時候就存在了,而開闢指標空間實際上是為指標所指向的結構體開闢一塊空間,這一操作只是讓這些被宣告好的指標有地方能指,而不是把指標放進去......(我自己也覺得這樣特地去說好像有點蠢......))
④將這個每個「表單元」初始化為empty
⑤返回這個表的位址
查詢關鍵字函式:
position find(int key, hashtable h)
return currentpos;
}
很有意思的函式,我最初並沒有看懂為什麼currentpos是那樣計算的,但從結論來說,作者說的對。
①宣告位置指標currentpos
②定義碰撞次數collisionnum=0
③得出其本該對應的雜湊值
④遍歷表。如果「該單元狀態非空,且關鍵字不相同」,碰撞次數增加,currentpos指標偏移乙個 collisionnum^2(並判斷是否超出了表的範圍,若超出就把它來回來)
最妙的就是偏移量計算了。它避免了一些看似需要的乘法和除法。書上還特別叮囑,不要改變while的判斷條件的先後順序(這是很有必要,也很有趣的方法。當你發現該單元格內資料為empty,則直接返回這個位址了,而不是返回null。這會為下乙個insert函式提供很多便利。並且,也是非常有必要的是,對於沒有初始化的單元格內的key,它無疑是有乙個確確實實的值的,這樣做能省下一點時間。)
f(i)=f(i-1)+2i-1這是書中給出的演算法,在計算機中並不難實現。
插入函式:
void insert(int key,hashtable h)
}
①宣告,並找出該關鍵字對應的pos位置
②如果這個關鍵字已經存在了,就什麼都不做;如果不存在,那就往裡面放新的關鍵字。
不妨假設現在的表中是不存在deleted狀態的單元格。那麼find函式只會返回legitimate或者empty。
返回legitimate狀態的條件,只有一種:①單元格不為空,關鍵字相同。此時,find函式會馬上返回legitimate
返回empty狀態的條件,也只有一種:①單元格為空,直接返回。
這樣的說明分明是沒必要的,但我寫出來才理順了。
刪除函式並沒有寫,我覺得那沒太大必要,就做些簡單的說明吧。
本例中,「刪除」操作並不是指把資料真的刪除,只是把單元格狀態標記為deleted罷了。資料仍然會被儲存。
如果真的想寫,和上面的insert差不多。直接用find找出來,判斷是否為empty就行了。
平方探測再雜湊怎麼算 電線的平方怎麼算?
電線怎麼看平方數?幾平方是國家標準規定的的乙個標稱值,幾平方是使用者根據電線電纜的負荷來選擇電線電纜。電線平方數是裝修水電施工中的乙個口頭用語,常說的幾平方電線是沒加單位,即平方公釐。1 整捆的新線,包裝表面會有線的標籤,清楚標註線的品牌 型號 線徑 電線的平方數 見下圖。2 有些大品牌的電線在絕緣...
開放定址法解決衝突的雜湊表
題目描述 找是否有兩片完全相同的雪花,雪花總數為 0 n 100000,判斷兩片雪花是否相同的標準為其中一片雪花的的六角陣列經過向左 右 迴圈移位後與另一片的六角陣列相同 pragma warning disable 4786 include include includeusing namespa...
整型關鍵字的平方探測法雜湊 25分
本題的任務很簡單 將給定的無重複正整數序列插入乙個雜湊表,輸出每個輸入的數字在表中的位置。所用的雜湊函式是 h key key tsize,其中 tsize 是雜湊表的表長。要求用平方探測法 只增不減,即h key i 2 解決衝突。注意雜湊表的表長最好是個素數。如果輸入給定的表長不是素數,你必須將...