#include
#include
#include
#include
//启用断言
#define DEBUG
#define HASH_MAX 101
#define ERR_EXIT(m) (perror(m), exit(EXIT_FAILURE))
typedef struct _hashnode //哈希结点
{
void *key;
void *value;
struct _hashnode *prev;
struct _hashnode *next;
} HASH_NODE;
typedef struct _hashlink //哈希链表
{
HASH_NODE *head;
HASH_NODE *rear;
unsigned int len;
} HASH_LINK;
typedef struct _hashtable //通用哈希表
{
unsigned int len;
unsigned int hash_max;
HASH_LINK *hash_link;
unsigned int (*T_hash_fun)(void *key);
} HASH_TABLE;
void* memdup(const void *src, unsigned int len);
void hash_init(HASH_TABLE **hash_table, unsigned int
(*hash_fun)(void *key));
void* hash_first_insert(HASH_TABLE *hash_table, void *key, unsigned
int key_len, void *val, unsigned int val_len);
void* hash_last_insert(HASH_TABLE *hash_table, void *key, unsigned
int key_len, void *val, unsigned int val_len);
int hash_first_delete(HASH_TABLE *hash_table, void* key, unsigned
int key_len, void *val, unsigned int val_len);
int hash_last_delete(HASH_TABLE *hash_table, void* key, unsigned
int key_len, void *val, unsigned int val_len);
int hash_first_set(HASH_TABLE *hash_table, void* key, unsigned int
key_len, void *val, unsigned int val_len);
int hash_last_set(HASH_TABLE *hash_table, void* key, unsigned int
key_len, void *val, unsigned int val_len);
HASH_NODE * hash_first_search(HASH_TABLE *hash_table, void *key,
unsigned int key_len, void *val, unsigned int val_len);
HASH_NODE * hash_last_search(HASH_TABLE *hash_table, void *key,
unsigned int key_len, void *val, unsigned int val_len);
void* hash_get_first_value(HASH_TABLE *hash_table, void* key,
unsigned int key_len);
void* hash_get_last_value(HASH_TABLE *hash_table, void* key,
unsigned int key_len);
void hash_clear(HASH_TABLE *hash_table);
void hash_destroy(HASH_TABLE **hash_table);
unsigned int hash_fun1(void *key);
unsigned int hash_fun2(void *key);
unsigned int hash_fun3(void *key);
unsigned int hash_fun4(void *key);
unsigned int hash_fun5(void *key);
unsigned int hash_fun6(void *key);
unsigned int hash_fun7(void *key);
unsigned int hash_fun8(void *key);
unsigned int hash_fun9(void *key);
unsigned int hash_fun10(void *key);
unsigned int hash_fun11(void *key);
void* memdup(const void *src, unsigned int len)
{
void *p;
if(!src)
return NULL;
p = malloc(len);
if(!p)
{
ERR_EXIT("memdup: malloc");
}
memcpy(p, src, len);
return p;
}
void hash_init(HASH_TABLE **hash_table, unsigned int
(*hash_fun)(void *key))
{
HASH_TABLE *hash;
#ifdef DEBUG
assert(NULL != hash_table);
assert(NULL != hash_fun);
#endif
*hash_table = (HASH_TABLE *)malloc(sizeof(HASH_TABLE));
hash = *hash_table;
if(!hash)
{
ERR_EXIT("hash_init: malloc");
}
hash->len = 0;
hash->hash_max = HASH_MAX;
hash->hash_link = (HASH_LINK *)calloc(HASH_MAX,
sizeof(HASH_LINK));
if(!(hash->hash_link))
{
ERR_EXIT("hash_init: calloc");
}
memset(hash->hash_link, 0, HASH_MAX *
sizeof(HASH_LINK));
hash->T_hash_fun = hash_fun;
}
void* hash_first_insert(HASH_TABLE *hash_table, void *key, unsigned
int key_len, void *val, unsigned int val_len)
{
unsigned int index;
HASH_NODE *phead, *tmp;
#ifdef DEBUG
assert(NULL != hash_table);
assert(NULL != key);
#endif
tmp = (HASH_NODE *)malloc(sizeof(HASH_NODE));
if(!tmp)
{
ERR_EXIT("hash_first_insert: malloc");
}
tmp->key = memdup(key, key_len);
tmp->value = memdup(val, val_len);
tmp->prev = tmp->next = NULL;
index = hash_table->T_hash_fun(key);
phead = hash_table->hash_link[index].head;
if(!phead)
{
hash_table->hash_link->head =
hash_table->hash_link->rear =
tmp;
} else
{
tmp->next = phead;
phead->prev = tmp;
phead = tmp;
}
hash_table->len += 1;
hash_table->hash_link[index].len += 1;
return tmp->key;
}
void* hash_last_insert(HASH_TABLE *hash_table, void *key, unsigned
int key_len, void *val, unsigned int val_len)
{
unsigned int index;
HASH_NODE *prear, *tmp;
#ifdef DEBUG
assert(NULL != hash_table);
assert(NULL != key);
#endif
tmp = (HASH_NODE *)malloc(sizeof(HASH_NODE));
if(!tmp)
{
ERR_EXIT("hash_first_insert: malloc");
}
tmp->key = memdup(key, key_len);
tmp->value = memdup(val, val_len);
tmp->prev = tmp->next = NULL;
index = hash_table->T_hash_fun(key);
prear = hash_table->hash_link[index].rear;
if(!prear)
{
hash_table->hash_link->head =
hash_table->hash_link->rear =
tmp;
} else
{
tmp->prev = prear;
prear->next = tmp;
prear = tmp;
}
hash_table->len += 1;
hash_table->hash_link[index].len += 1;
return tmp->key;
}
int hash_first_delete(HASH_TABLE *hash_table, void* key, unsigned
int key_len, void *val, unsigned int val_len)
{
unsigned int index;
HASH_NODE *p, *phead, *prear;
#ifdef DEBUG
assert(NULL != hash_table);
assert(NULL != key);
#endif
p = hash_first_search(hash_table, key, key_len, val,
val_len);
if(!p)
{
return 0;
}
index = hash_table->T_hash_fun(key);
phead = hash_table->hash_link[index].head;
prear = hash_table->hash_link[index].rear;
if(phead == p)
{
phead = phead->next;
hash_table->hash_link[index].head = phead;
}
else if(prear == p)
{
prear = prear->prev;
hash_table->hash_link[index].rear = prear;
}
else
{
p->prev->next =
p->next;
p->next->prev =
p->prev;
}
free(p->key);
free(p->value);
free(p);
if(!phead || !prear)
hash_table->hash_link[index].head =
hash_table->hash_link[index].rear = NULL;
hash_table->len -= 1;
hash_table->hash_link[index].len -= 1;
return 1;
}
int hash_last_delete(HASH_TABLE *hash_table, void* key, unsigned
int key_len, void *val, unsigned int val_len)
{
unsigned int index;
HASH_NODE *p, *phead, *prear;
#ifdef DEBUG
assert(NULL != hash_table);
assert(NULL != key);
#endif
p = hash_last_search(hash_table, key, key_len, val, val_len);
if(!p)
{
return 0;
}
index = hash_table->T_hash_fun(key);
phead = hash_table->hash_link[index].head;
prear = hash_table->hash_link[index].rear;
if(phead == p)
{
phead = phead->next;
hash_table->hash_link[index].head = phead;
}
else if(prear == p)
{
prear = prear->prev;
hash_table->hash_link[index].rear = prear;
}
else
{
p->prev->next =
p->next;
p->next->prev =
p->prev;
}
free(p->key);
free(p->value);
free(p);
if(!phead || !prear)
hash_table->hash_link[index].head =
hash_table->hash_link[index].rear = NULL;
hash_table->len -= 1;
hash_table->hash_link[index].len -= 1;
return 1;
}
int hash_first_set(HASH_TABLE *hash_table, void* key, unsigned int
key_len, void *val, unsigned int val_len)
{
HASH_NODE *p;
#ifdef DEBUG
assert(NULL != hash_table);
assert(NULL != key);
#endif
p = hash_first_search(hash_table, key, key_len, NULL, 0);
if(!p)
{
return 0;
}
p->value = memdup(val, val_len);
return 1;
}
int hash_last_set(HASH_TABLE *hash_table, void* key, unsigned int
key_len, void *val, unsigned int val_len)
{
HASH_NODE *p;
#ifdef DEBUG
assert(NULL != hash_table);
assert(NULL != key);
#endif
p = hash_last_search(hash_table, key, key_len, NULL, 0);
if(!p)
{
return 0;
}
p->value = memdup(val, val_len);
return 1;
}
HASH_NODE * hash_first_search(HASH_TABLE *hash_table, void *key,
unsigned int key_len, void *val, unsigned int val_len)
{
unsigned int index;
HASH_NODE *p = NULL;
#ifdef DEBUG
assert(NULL != hash_table);
assert(NULL != key);
#endif
index = hash_table->T_hash_fun(key);
p = hash_table->hash_link[index].head;
if(val)
{
for(; p; p = p->next)
{
if(!memcmp(p->key, key, key_len)
&& !memcmp(p->value,
val, val_len))
return p;
}
} else
{
for(; p; p = p->next)
{
if(!memcmp(p->key, key, key_len))
return p;
}
}
return NULL;
}
HASH_NODE * hash_last_search(HASH_TABLE *hash_table, void *key,
unsigned int key_len, void *val, unsigned int val_len)
{
unsigned int index;
HASH_NODE *p = NULL;
#ifdef DEBUG
assert(NULL != hash_table);
assert(NULL != key);
#endif
index = hash_table->T_hash_fun(key);
p = hash_table->hash_link[index].rear;
if(val)
{
for(; p; p = p->prev)
{
if(!memcmp(p->key, key, key_len)
&& !memcmp(p->value,
val, val_len))
return p;
}
} else
{
for(; p; p = p->prev)
{
if(!memcmp(p->key, key, key_len))
return p;
}
}
return NULL;
}
void* hash_get_first_value(HASH_TABLE *hash_table, void* key,
unsigned int key_len)
{
HASH_NODE *p;
#ifdef DEBUG
assert(NULL != hash_table);
assert(NULL != key);
#endif
p = hash_first_search(hash_table, key, key_len, NULL, 0);
if(!p)
{
return NULL;
}
return p->value;
}
void* hash_get_last_value(HASH_TABLE *hash_table, void* key,
unsigned int key_len)
{
HASH_NODE *p;
#ifdef DEBUG
assert(NULL != hash_table);
assert(NULL != key);
#endif
p = hash_last_search(hash_table, key, key_len, NULL, 0);
if(!p)
{
return NULL;
}
return p->value;
}
void hash_clear(HASH_TABLE *hash_table)
{
int i;
HASH_NODE *p;
#ifdef DEBUG
assert(NULL != hash_table);
#endif
for(i=0; i
{
if(hash_table->hash_link[i].head)
{
while(p = hash_table->hash_link[i].head)
{
hash_table->hash_link[i].head =
hash_table->hash_link[i].head->next;
free(p->key);
free(p->value);
free(p);
} //while
} //if
} //for
memset(hash_table->hash_link, 0, HASH_MAX *
sizeof(HASH_LINK));
hash_table->len = 0;
}
void hash_destroy(HASH_TABLE **hash_table)
{
int i;
HASH_NODE *p;
HASH_TABLE *hash;
#ifdef DEBUG
assert(NULL != hash_table);
#endif
hash = *hash_table;
for(i=0; i
{
if(hash->hash_link[i].head)
{
while(p = hash->hash_link[i].head)
{
hash->hash_link[i].head =
hash->hash_link[i].head->next;
free(p->key);
free(p->value);
free(p);
} //while
} //if
} //for
free(hash->hash_link);
free(hash);
*hash_table = NULL;
}
unsigned int hash_fun1(void* str)
{
char *tmp;
unsigned int b = 378551;
unsigned int a = 63689;
unsigned int hash = 0;
unsigned int i = 0;
tmp = (char *)str;
while(*tmp)
{
hash = hash * a + (*tmp++);
a = a * b;
}
return hash % HASH_MAX;
}
unsigned int hash_fun2(void *key)
{
char *tmp = (char *)key;
unsigned int hash = 1315423911;
unsigned int i = 0;
while(*tmp)
{
hash ^= ((hash << 5) + (*tmp++) +
(hash >> 2));
}
return hash % HASH_MAX;
}
unsigned int hash_fun3(void *key)
{
char *tmp = (char *)key;
const unsigned int BitsInUnsignedInt = (unsigned
int)(sizeof(unsigned int) * 8);
const unsigned int ThreeQuarters = (unsigned
int)((BitsInUnsignedInt * 3) / 4);
const unsigned int OneEighth = (unsigned int)(BitsInUnsignedInt /
8);
const unsigned int HighBits = (unsigned int)(0xFFFFFFFF)
<< (BitsInUnsignedInt -
OneEighth);
unsigned int hash = 0;
unsigned int test = 0;
unsigned int i = 0;
while(*tmp)
{
hash = (hash << OneEighth) +
(*tmp++);
if((test = hash & HighBits) != 0)
{
hash = (( hash ^ (test >>
ThreeQuarters)) & (~HighBits));
}
}
return hash % HASH_MAX;
}
unsigned int hash_fun4(void *key)
{
char *tmp = (char *)key;
unsigned int hash = 0;
unsigned int x = 0;
unsigned int i = 0;
while(*tmp)
{
hash = (hash << 4) + (*tmp++);
if((x = hash & 0xF0000000L) != 0)
{
hash ^= (x >> 24);
}
hash &= ~x;
}
return hash % HASH_MAX;
}
unsigned int hash_fun5(void *key)
{
char *tmp;
unsigned int hash = 0;
tmp = (char*)key;
hash = 0;
while(*tmp)
{
hash = (*tmp++) + hash*131;
}
return hash % HASH_MAX;
}
unsigned int hash_fun6(void *key)
{
char *tmp = (char *)key;
unsigned int hash = 0;
unsigned int i = 0;
while(*tmp)
{
hash = (*tmp++) + (hash << 6) + (hash
<< 16) - hash;
}
return hash % HASH_MAX;
}
unsigned int hash_fun7(void *key)
{
char *tmp = (char *)key;
unsigned int hash = 5381;
unsigned int i = 0;
while(*tmp)
{
hash = ((hash << 5) + hash) +
(*tmp++);
}
return hash % HASH_MAX;
}
unsigned int hash_fun8(void *key)
{
char *tmp = (char *)key;
unsigned int hash = strlen(tmp);
unsigned int i = 0;
while(*tmp)
{
hash = ((hash << 5) ^ (hash
>> 27)) ^ (*tmp++);
}
return hash % HASH_MAX;
}
unsigned int hash_fun9(void *key)
{
char *tmp = (char *)key;
unsigned int hash = 0;
unsigned int i = 0;
while(*tmp)
{
hash = hash << 7 ^ (*tmp++);
}
return hash % HASH_MAX;
}
unsigned int hash_fun10(void *key)
{
char *tmp = (char *)key;
const unsigned int fnv_prime = 0x811C9DC5;
unsigned int hash = 0;
unsigned int i = 0;
while(*tmp)
{
hash *= fnv_prime;
hash ^= (*tmp++);
}
return hash % HASH_MAX;
}
unsigned int hash_fun11(void *key)
{
char *tmp = (char *)key;
unsigned int hash = 0xAAAAAAAA;
unsigned int i = 0;
while(*tmp)
{
hash ^= ((i & 1) == 0) ? ( (hash
<< 7) ^ (*tmp++) * (hash
>> 3)) :
(~((hash << 11) + ((*tmp++) ^ (hash
>> 5))));
}
return hash % HASH_MAX;
}
int main()
{
unsigned int (*HASH_FUN[])(void *) =
{ hash_fun1, hash_fun2, hash_fun3, hash_fun4, hash_fun5,
hash_fun6, hash_fun7, hash_fun8, hash_fun9, hash_fun10,
hash_fun11
};
char *keywords[] =
{
"auto","break","case","char","const","continue","default","do",
"double","else","enum","extern","float","for","goto","if",
"int","long","register","return","short","signed","sizeof","static",
"struct","switch","typedef","union","unsigned","void","volatile","while",
"auto1","break1","case1","char1","const1","continue1","default1","do1",
"double1","else1","enum1","extern1","float1","for1","goto1","if1",
"int1","long1","registe1r","return1","short1","signed1","sizeof1","static1",
"struct1","switch1","typedef1","union1","unsigned1","void1","volatile1","while1",
"auto2","br2eak","ca2se","c2har","con2st","c2ontinue","de2fault","d2o",
"double22","els2e","enum2","ext2ern","flo2at","fo2r","go2to","i2f",
"int2","l2ong","regist2er","ret2urn","shor2t","sign2ed","siz2eof","st2atic",
"struct2","switch2","typedef2","union2","unsigned2","void2","volat2ile","w2hile",
"au3to","br3eak","ca3se","ch3ar","co3nst","co3ntinue","def3ault","3do",
"doub3le","els3e","enu3m","ext3ern","floa3t","fo3r","go3to","3if",
"in3t","lo3ng","re3gister","r3eturn","s3hort","si3gned","s3izeof","sta3tic",
"struc3t","swi3tch","typ3edef","uni3on","unsi3gned","v3oid","vola3tile","wh3ile",
"1", "3", "5", "7", "9", "12", "45", "78",
"2", "4", "6", "8", "0", "21", "54", "87",
"11", "33", "55", "77", "99", "23", "56", "89",
"22", "44", "66", "88", "00", "98", "32", "65",
"111", "333", "555", "777", "999", "34", "67", "90",
"222", "444", "666", "888", "000", "43", "76", "09",
"1a", "3b", "5c", "7dddddd", "9eeeeee", "12f", "45gggggg",
"78h",
"2aa", "4bb", "6cccccc", "8ddddd", "0eeeee", "21ff", "54ggggg",
"87hh",
"11aaa", "33bbb", "55ccccc", "77dddd", "99eeee", "23fff", "56gggg",
"89hhh",
"22aaaa", "44bbbb", "66cccc", "88ddd", "00eee", "98ffff", "32ggg",
"65hhhh",
"111aaaaa", "333bbbbb", "555ccc", "777dd", "999ee", "34fffff",
"67gg", "90hhhhh",
"222aaaaaa", "444bbbbbb", "666cc", "888d", "000e", "43ffffff",
"76g", "09hhhhhh"
};
int i, j, size, sum[11] = {0};
HASH_TABLE *hash_table[11];
for(i=0; i<11; i++)
hash_init(hash_table+i, HASH_FUN[i]);
size = sizeof(keywords) / sizeof(keywords[0]);
for(i=0; i<11; i++)
{
for(j=0; j
{
hash_first_insert(hash_table[i], keywords[j], sizeof(keywords[j]),
NULL, 0);
}
}
for(i=0; i<11; i++)
{
for(j=0; j
{
if(0 == hash_table[i]->hash_link[j].len)
sum[i]++;
}
}
for(i=0; i<11; i++)
{
printf("\n%d: 总数: %d, 哈希链表长度为0的数目: %d\n",
i+1, hash_table[i]->len, sum[i]);
hash_destroy(hash_table+i);
}
return 0;
}