常用哈希函数的比较及其实现
基本概念
所謂完美哈希函數。就是指沒有沖突的哈希函數。即對隨意的 key1 != key2 有h(key1) != h(key2)。
設定義域為X,值域為Y, n=|X|,m=|Y|。那么肯定有m>=n,假設對于不同的key1,key2屬于X,有h(key1)!=h(key2),那么稱h為完美哈希函數,當m=n時,h稱為最小完美哈希函數(這個時候就是一一映射了)。
在處理大規模字符串數據時。常常要為每一個字符串分配一個整數ID。這就須要一個字符串的哈希函數。怎么樣找到一個完美的字符串hash函數呢?
有一些經常使用的字符串hash函數。
像BKDRHash,APHash。DJBHash。JSHash,RSHash。SDBMHash,PJWHash。ELFHash等等。都是比較經典的。
經常使用的字符串Hash函數還有ELFHash,APHash等等,都是十分簡單有效的方法。
這些函數使用位運算使得每個字符都對最后的函數值產生影響。另外還有以MD5和SHA1為代表的雜湊函數。這些函數差點兒不可能找到碰撞。
經常使用字符串哈希函數有 BKDRHash。APHash。DJBHash,JSHash,RSHash,SDBMHash,PJWHash,ELFHash等等。對于以上幾種哈希函數。我對其進行了一個小小的評測。
| Hash函數 | 數據1 | 數據2 | 數據3 | 數據4 | 數據1得分 | 數據2得分 | 數據3得分 | 數據4得分 | 平均分 |
| BKDRHash | 2 | 0 | 4774 | 481 | 96.55 | 100 | 90.95 | 82.05 | 92.64 |
| APHash | 2 | 3 | 4754 | 493 | 96.55 | 88.46 | 100 | 51.28 | 86.28 |
| DJBHash | 2 | 2 | 4975 | 474 | 96.55 | 92.31 | 0 | 100 | 83.43 |
| JSHash | 1 | 4 | 4761 | 506 | 100 | 84.62 | 96.83 | 17.95 | 81.94 |
| RSHash | 1 | 0 | 4861 | 505 | 100 | 100 | 51.58 | 20.51 | 75.96 |
| SDBMHash | 3 | 2 | 4849 | 504 | 93.1 | 92.31 | 57.01 | 23.08 | 72.41 |
| PJWHash | 30 | 26 | 4878 | 513 | 0 | 0 | 43.89 | 0 | 21.95 |
| ELFHash | 30 | 26 | 4878 | 513 | 0 | 0 | 43.89 | 0 | 21.95 |
當中數據1為100000個字母和數字組成的隨機串哈希沖突個數。
?
數據2為100000個有意義的英文句子哈希沖突個數。數據3為數據1的哈希值與 1000003(大素數)求模后存儲到線性表中沖突的個數。
數據4為數據1的哈希值與10000019(更大素數)求模后存儲到線性表中沖突的個數。
經過比較。得出以上平均得分。
平均數為平方平均數。能夠發現,BKDRHash不管是在實際效果還是編碼實現中。效果都是最突出的。APHash也是較為優秀的算法。DJBHash,JSHash,RSHash與SDBMHash各有千秋。PJWHash與ELFHash效果最差,但得分相似,其算法本質是相似的。
C語言實現的hash()如下:
unsigned int SDBMHash(char *str) {unsigned int hash = 0;while (*str){// equivalent to: hash = 65599*hash + (*str++);hash = (*str++) + (hash << 6) + (hash << 16) - hash;}return (hash & 0x7FFFFFFF); }// RS Hash Function unsigned int RSHash(char *str) {unsigned int b = 378551;unsigned int a = 63689;unsigned int hash = 0;while (*str){hash = hash * a + (*str++);a *= b;}return (hash & 0x7FFFFFFF); }// JS Hash Function unsigned int JSHash(char *str) {unsigned int hash = 1315423911;while (*str){hash ^= ((hash << 5) + (*str++) + (hash >> 2));}return (hash & 0x7FFFFFFF); }// P. J. Weinberger Hash Function unsigned int PJWHash(char *str) {unsigned int BitsInUnignedInt = (unsigned int)(sizeof(unsigned int) * 8);unsigned int ThreeQuarters = (unsigned int)((BitsInUnignedInt * 3) / 4);unsigned int OneEighth = (unsigned int)(BitsInUnignedInt / 8);unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnignedInt - OneEighth);unsigned int hash = 0;unsigned int test = 0;while (*str){hash = (hash << OneEighth) + (*str++);if ((test = hash & HighBits) != 0){hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits));}}return (hash & 0x7FFFFFFF); }// ELF Hash Function unsigned int ELFHash(char *str) {unsigned int hash = 0;unsigned int x = 0;while (*str){hash = (hash << 4) + (*str++);if ((x = hash & 0xF0000000L) != 0){hash ^= (x >> 24);hash &= ~x;}}return (hash & 0x7FFFFFFF); }// BKDR Hash Function unsigned int BKDRHash(char *str) {unsigned int seed = 131; // 31 131 1313 13131 131313 etc..unsigned int hash = 0;while (*str){hash = hash * seed + (*str++);}return (hash & 0x7FFFFFFF); }// DJB Hash Function unsigned int DJBHash(char *str) {unsigned int hash = 5381;while (*str){hash += (hash << 5) + (*str++);}return (hash & 0x7FFFFFFF); }// AP Hash Function unsigned int APHash(char *str) {unsigned int hash = 0;int i;for (i=0; *str; i++){if ((i & 1) == 0){hash ^= ((hash << 7) ^ (*str++) ^ (hash >> 3));}else{hash ^= (~((hash << 11) ^ (*str++) ^ (hash >> 5)));}}return (hash & 0x7FFFFFFF); }上面部分參考了:https://www.cnblogs.com/yxwkf/p/5397780.html
或者使用模板的方式(C++)://6種字符串哈希算法
template<class T> size_t BKDRHash(const T * str) {register size_t hash = 0;while (size_t ch = (size_t)*str++){hash = hash * 131 + ch; // 也可以乘以31、131、1313、13131、131313.. }return hash; } template<class T> size_t SDBMHash(const T *str) {register size_t hash = 0;while (size_t ch = (size_t)*str++){hash = 65599 * hash + ch;//hash = (size_t)ch + (hash << 6) + (hash << 16) - hash; }return hash; } template<class T> size_t RSHash(const T *str) {register size_t hash = 0;size_t magic = 63689;while (size_t ch = (size_t)*str++){hash = hash * magic + ch;magic *= 378551;}return hash; } template<class T> size_t APHash(const T *str) {register size_t hash = 0;size_t ch;for (long i = 0; ch = (size_t)*str++; i++){if ((i & 1) == 0){hash ^= ((hash << 7) ^ ch ^ (hash >> 3));}else{hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));}}return hash; } template<class T> size_t JSHash(const T *str) {if (!*str) // 這是由本人添加,以保證空字符串返回哈希值0 return 0;register size_t hash = 1315423911;while (size_t ch = (size_t)*str++){hash ^= ((hash << 5) + ch + (hash >> 2));}return hash; } template<class T> size_t DEKHash(const T* str) {if (!*str) // 以保證空字符串返回哈希值0 return 0;register size_t hash = 1315423911;while (size_t ch = (size_t)*str++){hash = ((hash << 5) ^ (hash >> 27)) ^ ch;}return hash; }?
總結
以上是生活随笔為你收集整理的常用哈希函数的比较及其实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 海伊视讯布控球对接海康Ehome协议平台
- 下一篇: AE动画导出json工具:bodymov