经典字符串HASH函数

来源:互联网 发布:软件项目质量计划 编辑:程序博客网 时间:2024/05/02 21:32
//1. PHP中出现的字符串Hash函数
    
static unsigned long hashpjw(char *arKey, unsigned int nKeyLength)
{
unsigned long h = 0, g;
char *arEnd=arKey+nKeyLength;
    
while (arKey < arEnd)
{
h = (h << 4) + *arKey++;
if ((g = (h & 0xF0000000)))
{
h = h ^ (g >> 24);
h = h ^ g;
}
}

return h;
}
    
//2. OpenSSL中出现的字符串Hash函数
    
unsigned long lh_strhash(char *str)
{
int i,l;
unsigned long ret=0;
unsigned short *s;
    
if (str == NULL) return 0;
l=(strlen(str)+1)/2;
s=(unsigned short *)str;
for (i=0; i ret^=(s[i]<<(i&0x0f));

return ret;
}
/* 
* The following hash seems to work very well on normal text strings
* distributes on %2^n quite well, not as good as MD5, but still good.
*/
unsigned long lh_strhash(const char *c)
{
unsigned long ret=0;
long n;
unsigned long v;
int r;
    
if ((c == NULL) || (*c == '\0')) return(ret);
/*
unsigned char b[16];
MD5(c,strlen(c),b);
return(b[0]|(b[1]<<8)|(b[2]<<16)|(b[3]<<24)); 
*/
n=0x100;
while (*c)
{
v=n|(*c);
n+=0x100;
r= (int)((v>>2)^v)&0x0f;
ret=(ret(32-r));
ret&=0xFFFFFFFFL;
ret^=v*v;
c++;
}

return((ret>>16)^ret);
}
    
    
//3. MySql中出现的字符串Hash函数(Mysql中对字符串Hash函数还区分了大小写)
    
#ifndef NEW_HASH_FUNCTION
    
/* Calc hashvalue for a key */
static uint calc_hashnr(const byte *key,uint length)
{
register uint nr=1, nr2=4;

while (length--)
{
nr^= (((nr & 63)+nr2)*((uint) (uchar) *key++))+ (nr << 8);
nr2+=3;
}

return((uint) nr);
}
    
/* Calc hashvalue for a key, case indepenently */
static uint calc_hashnr_caseup(const byte *key,uint length)
{
register uint nr=1, nr2=4;

while (length--)
{
nr^= (((nr & 63)+nr2)*((uint) (uchar) toupper(*key++)))+ (nr << 8);
nr2+=3;
}

return((uint) nr);
}
    
#else
    
/*
* Fowler/Noll/Vo hash
*
* The basis of the hash algorithm was taken from an idea sent by email to the
* 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)
{
const byte *end=key+len;
uint hash;

for (hash = 0; key < end; key++)
{
hash *= 16777619;
hash ^= (uint) *(uchar*) key;
}

return (hash);
}
    
uint calc_hashnr_caseup(const byte *key, uint len)
{
const byte *end=key+len;
uint hash;

for (hash = 0; key < end; key++)
{
hash *= 16777619;
hash ^= (uint) (uchar) toupper(*key);
}

return (hash);
}
    
#endif
    
    
//4. 一个开源的哈希表源码实现
struct entry
{
void *k, *v;
unsigned int h;
struct entry *next;
};
struct hashtable {
unsigned int tablelength;
struct entry **table;
unsigned int entrycount;
unsigned int loadlimit;
unsigned int primeindex;
unsigned int (*hashfn) (void *k);
int (*eqfn) (void *k1, void *k2);
};
  
static const unsigned int primes[] = {
53, 97, 193, 389,
769, 1543, 3079, 6151,
12289, 24593, 49157, 98317,
196613, 393241, 786433, 1572869,
3145739, 6291469, 12582917, 25165843,
50331653, 100663319, 201326611, 402653189,
805306457, 1610612741
};

const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
const float max_load_factor = 0.65;
  
struct hashtable *create_hashtable(unsigned int minsize, unsigned int (*hashf) (void*),
int (*eqf) (void*,void*))
{
struct hashtable *h;
unsigned int pindex, size = primes[0];
/* Check requested hashtable isn't too large */
if (minsize > (1u << 30)) return NULL;
/* Enforce size as prime */
for (pindex=0; pindex < prime_table_length; pindex++)
{
if (primes[pindex] > minsize) 

size=prime[pindex]; 
break; 
}
}
h = (struct hashtable *)malloc(sizeof(struct hashtable));
if (NULL == h) return NULL; /*oom*/
h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
if (NULL == h->table) 

free(h); 
return NULL; 
} /*oom*/
memset(h->table, 0, size * sizeof(struct entry *));
h->tablelength = size;
h->primeindex = pindex;
h->entrycount = 0;
h->hashfn = hashf;
h->eqfn = eqf;
h->loadlimit = (unsigned int) ceil(size * max_load_factor);

return h;
}
  
unsigned int hash(struct hashtable *h, void *k)
{
/* Aim to protect against poor hash functions by adding logic here - logic taken from java 1.4 hashtable source */
unsigned int i = h->hashfn(k);

i += ~(i << 9);
i ^= ((i >> 14) | (i << 18)); /* >>> */
i += (i << 4);
i ^= ((i >> 10) | (i << 22)); /* >>> */

return i;
}
  
  
5. 另一些字符串Hash函数
    
unsigned int hash(char *str)
{
register unsigned int h;
register unsigned char *p;
    
for(h=0, p = (unsigned char *)str; *p ; p++)
h = 31 * h + *p;
    
return h;
}
    
unsigned int hash_func(char *str, int len)
{
register unsigned int sum = 0; 
register unsigned int h = 0;
register char *p = str;
    
while(p - s < len) 
{
register unsigned short a = *(p++);
sum ^= a * (p - str); 
h ^= a / (p - str);
}

return ((sum << 16) | h) % MAX_PRIME_LESS_THAN_HASH_LEN;
}
    
// 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 ,The mostly frequntly used one
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);

    
// SDBM Hash Function 
unsigned int SDBMHash( char * str)
{
unsigned int hash = 0;
    
while ( * str)
hash = ( *str++ ) + ( hash << 6 ) + (hash << 16 ) - hash;

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 nt 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 );
原创粉丝点击