哈希函數的構造及注意事項

哈希表的主要作用其實就是處理數據的映射,把數據轉換爲更方便,更容易處理的數據。

而映射就是就是一個函數,稱之爲哈希函數。

 

通常構造哈希函數需要考慮以下要點:

(1)哈希函數的耗時時間

(2)關鍵字的長度

(3)哈希表的大小

(4)關鍵字的分佈情況

(5)記錄的查找頻率

 

下面只介紹構造哈希函數最常用的方法也是很簡單的方法:

除留餘數法

取關鍵字被某個不大於哈希表表長m的數p除後所得餘數爲哈希地址。

H(key)=key MOD p (p<=m)

 

所謂的哈希表表長,就是你計劃定義的數組元素個數的大小。

 

 

衝突的處理方法

設置的哈希函數一般可以減少衝突,但避免不了。所以,需要有針對衝突的處理方式。

 

衝突處理:令數組元素個數爲m ,則當H(key) 已經存儲了元素的時候,依次探查 (H(key)+i) modp , i=1,2,3……,直到找到空的存儲單元爲止(或者從頭到尾掃描一圈仍未發現空單元,這就是哈希表已經滿了,發生了錯誤。當然這是可以通過擴大數組範圍避免的)。

 

其實意思就是如果H(key)值已經被其他元素佔用了,試下H(key)+1,2,3...

 

另外一個就是求模時的p儘量使用素數,不選素數的話可能會造成hash出值的範圍和原定義的不一致哈希函數。

 

 

舉個例子

好的HASH函數需要把原始數據均勻地分佈到HASH數組裏

原始數據不大會是真正的隨機的,可能有某些規律,

比如大部分是偶數,這時候如果HASH數組容量是偶數,容易使原始數據HASH後不會均勻分佈。
比如 2 4 6 8 10 126個數,如果對6 取餘 得到2 4 0 2 4 0 只會得到3HASH值,衝突會很多
如果對 7 取餘 得到 2 4 6 1 3 5 得到6HASH值,沒有衝突

同樣地,如果數據都是3的倍數,而HASH數組容量是3的倍數,HASH後也容易有衝突

 

#ifndef _HASH_H_
#define _HASH_H_

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>

#define HASH_GENE 4
#define OVER_ (65535*65535)

int hash(char *key_str, unsigned long MAX_SS_NUM);

#endif //_HASH_H_

hash.c

#include "hash.h"

int hash(char *key_str, unsigned long MAX_SS_NUM)
{
register unsigned int h;
register unsigned char *p;

for(h=0, p = (unsigned char *)key_str; *p ; p++)
{
h = 31 * h + *p;
}

return (h % MAX_SS_NUM);
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章