版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://escorter.blogbus.com/logs/35660363.html
将一个字符串的数组中的每个元素依次按前四位与上一个元素的低四位相与,组成一个长整形,如果长整的高四位大于零,那么就将它折回再与长整的低四位相异或,这样最后得到的长整对HASH表长取余,得到在HASH中的位置。
经典字符串Hash函数测试 |
01-8-22 上午 11:50:37
|
| 链表查找的时间效率为O(N),二分法为log2N,B+ Tree为log2N,但Hash链表查找的时间效率为O(1)。 |
| 设计高效算法往往需要使用Hash链表,常数级的查找速度是任何别的算法无法比拟的,Hash链表的构造和冲突的不同实现方法对效率当然有一定的影响,然而Hash函数是Hash链表最核心的部分,本文尝试分析一些经典软件中使用到的字符串Hash函数在执行效率、离散性、空间利用率等方面的性能问题。 |
| 作者阅读过大量经典软件原代码,下面分别介绍几个经典软件中出现的字符串Hash函数。 |
| static unsigned long hashpjw(char *arKey, unsigned int nKeyLength) |
| char *arEnd=arKey+nKeyLength; |
| if ((g = (h & 0xF0000000))) { |
| unsigned long lh_strhash(char *str) |
| if (str == NULL) return(0); |
| /* The following hash seems to work very well on normal text strings |
| * no collisions on /usr/dict/words and it distributes on %2^n quite |
| * well, not as good as MD5, but still good. |
| unsigned long lh_strhash(const char *c) |
| if ((c == NULL) || (*c == '/0')) |
| return(b[0]|(b[1]<<8)|(b[2]<<16)|(b[3]<<24)); |
| 在下面的测量过程中我们分别将上面的两个函数标记为OpenSSL_Hash1和OpenSSL_Hash2,至于上面的实现中使用MD5算法的实现函数我们不作测试。 |
| #ifndef NEW_HASH_FUNCTION |
| /* Calc hashvalue for a key */ |
| static uint calc_hashnr(const byte *key,uint length) |
| register uint nr=1, nr2=4; |
| nr^= (((nr & 63)+nr2)*((uint) (uchar) *key++))+ (nr << 8); |
| /* Calc hashvalue for a key, case indepenently */ |
| static uint calc_hashnr_caseup(const byte *key,uint length) |
| register uint nr=1, nr2=4; |
| nr^= (((nr & 63)+nr2)*((uint) (uchar) toupper(*key++)))+ (nr << 8); |
| * IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and |
| * Glenn Fowler (gsf@research.att.com). Landon Curt Noll (chongo@toad.com) |
| * later improved on their algorithm. |
| * The magic is in the interesting relationship between the special prime |
| * 16777619 (2^24 + 403) and 2^32 and 2^8. |
| * This hash produces the fewest collisions of any function that we've seen so |
| * far, and works well on both numbers and strings. |
| uint calc_hashnr(const byte *key, uint len) |
| for (hash = 0; key < end; key++) |
| hash ^= (uint) *(uchar*) key; |
| uint calc_hashnr_caseup(const byte *key, uint len) |
| for (hash = 0; key < end; key++) |
| hash ^= (uint) (uchar) toupper(*key); |
| Mysql中对字符串Hash函数还区分了大小写,我们的测试中使用不区分大小写的字符串Hash函数,另外我们将上面的两个函数分别记为MYSQL_Hash1和MYSQL_Hash2。 |
| unsigned int hash(char *str) |
| register unsigned char *p; |
| for(h=0, p = (unsigned char *)str; *p ; p++) |
|