随便贴一个libhash中的hash函数,写的貌似不错,贴出来玩玩。
hash.h
/*
* Australian Public Licence B (OZPLB)
*
* Version 1-0
*
* Copyright (c) 2004 National ICT Australia
*
* All rights reserved.
*
* Developed by: Embedded, Real-time and Operating Systems Program (ERTOS)
* National ICT Australia
* http://www.ertos.nicta.com.au
*/
#ifndef _HASH_H
#define _HASH_H
#include <stdint.h>
struct hashtable {
struct hashentry **table;
unsigned int size;
struct hashentry *spares;
};
struct hashentry {
struct hashentry *next;
uintptr_t key;
void *value;
};
struct hashtable *hash_init (unsigned int size);
void hash_free (struct hashtable *tablestruct);
uintptr_t hash_hash(uintptr_t key);
void *hash_lookup (struct hashtable *tablestruct, uintptr_t key);
int hash_insert (struct hashtable *tablestruct, uintptr_t key, void *value);
void hash_remove (struct hashtable *tablestruct, uintptr_t key);
#endif /* !_HASH_H */
* Australian Public Licence B (OZPLB)
*
* Version 1-0
*
* Copyright (c) 2004 National ICT Australia
*
* All rights reserved.
*
* Developed by: Embedded, Real-time and Operating Systems Program (ERTOS)
* National ICT Australia
* http://www.ertos.nicta.com.au
*/
#ifndef _HASH_H
#define _HASH_H
#include <stdint.h>
struct hashtable {
struct hashentry **table;
unsigned int size;
struct hashentry *spares;
};
struct hashentry {
struct hashentry *next;
uintptr_t key;
void *value;
};
struct hashtable *hash_init (unsigned int size);
void hash_free (struct hashtable *tablestruct);
uintptr_t hash_hash(uintptr_t key);
void *hash_lookup (struct hashtable *tablestruct, uintptr_t key);
int hash_insert (struct hashtable *tablestruct, uintptr_t key, void *value);
void hash_remove (struct hashtable *tablestruct, uintptr_t key);
#endif /* !_HASH_H */
hash.c
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include "hash.h"
struct hashtable *
hash_init (unsigned int size)
{
struct hashtable *tablestruct;
int counter;
/* Our hash function only works with power-of-2 bucket sizes for speed. */
assert ((size & (size -1)) == 0);
tablestruct = malloc (sizeof (struct hashtable)); assert (tablestruct);
if (!tablestruct) {
return NULL;
}
tablestruct->table = malloc (size * sizeof (struct hashentry *));
if (!tablestruct->table) {
return NULL;
}
for (counter=0; counter<size; counter++) {
tablestruct->table[counter] = NULL;
}
assert (tablestruct->table);
tablestruct->size = size;
tablestruct->spares = NULL;
return tablestruct;
}
/* Ref http://www.concentric.net/~Ttwang/tech/inthash.htm */
uintptr_t
hash_hash(uintptr_t key)
{
#if (UINTPTR_MAX == UINT32_MAX)
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
#elif (UINTPTR_MAX == UINT64_MAX)
key += ~(key << 32);
key ^= (key >> 22);
key += ~(key << 13);
key ^= (key >> 8);
key += (key << 3);
key ^= (key >> 15);
key += ~(key << 27);
key ^= (key >> 31);
#else
#error unsupported word size
#endif
//printf ("new key is %d ", key);
return key;
}
void *
hash_lookup (struct hashtable *tablestruct, uintptr_t key)
{
uintptr_t hash;
struct hashentry *entry;
hash = hash_hash (key) & (tablestruct->size - 1);
for (entry = tablestruct->table[hash]; entry != NULL; entry = entry->next) {
if (entry->key == key) {
return entry->value;
}
}
return NULL;
}
/* Add the key to the hash table. Assumes the key is not already present. */
int
hash_insert (struct hashtable *tablestruct, uintptr_t key, void *value)
{
uintptr_t hash;
struct hashentry *entry;
hash = hash_hash (key) & (tablestruct->size - 1);
//printf ("bucket is %d ", hash);
entry = malloc (sizeof (struct hashentry));
if (!entry) {
return -1;
}
entry->key = key;
entry->value = value;
entry->next = tablestruct->table[hash];
tablestruct->table[hash] = entry;
return 0;
}
/* Removes the key from the hash table. Does not signal an error if the key
* was not present. */
void
hash_remove (struct hashtable *tablestruct, uintptr_t key)
{
uintptr_t hash;
struct hashentry *entry, *tmpentry;
hash = hash_hash (key) & (tablestruct->size - 1);
entry = tablestruct->table[hash];
/* If this is the first entry then it needs special handling. */
if (entry && entry->key == key) {
tmpentry = entry->next;
free (entry);
tablestruct->table[hash] = tmpentry;
} else {
while (entry) {
if (entry->next && entry->next->key == key) {
tmpentry = entry->next;
entry->next = entry->next->next;
free (tmpentry);
break;
}
entry = entry->next;
}
}
}
#include <stdlib.h>
#include <assert.h>
#include "hash.h"
struct hashtable *
hash_init (unsigned int size)
{
struct hashtable *tablestruct;
int counter;
/* Our hash function only works with power-of-2 bucket sizes for speed. */
assert ((size & (size -1)) == 0);
tablestruct = malloc (sizeof (struct hashtable)); assert (tablestruct);
if (!tablestruct) {
return NULL;
}
tablestruct->table = malloc (size * sizeof (struct hashentry *));
if (!tablestruct->table) {
return NULL;
}
for (counter=0; counter<size; counter++) {
tablestruct->table[counter] = NULL;
}
assert (tablestruct->table);
tablestruct->size = size;
tablestruct->spares = NULL;
return tablestruct;
}
/* Ref http://www.concentric.net/~Ttwang/tech/inthash.htm */
uintptr_t
hash_hash(uintptr_t key)
{
#if (UINTPTR_MAX == UINT32_MAX)
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
#elif (UINTPTR_MAX == UINT64_MAX)
key += ~(key << 32);
key ^= (key >> 22);
key += ~(key << 13);
key ^= (key >> 8);
key += (key << 3);
key ^= (key >> 15);
key += ~(key << 27);
key ^= (key >> 31);
#else
#error unsupported word size
#endif
//printf ("new key is %d ", key);
return key;
}
void *
hash_lookup (struct hashtable *tablestruct, uintptr_t key)
{
uintptr_t hash;
struct hashentry *entry;
hash = hash_hash (key) & (tablestruct->size - 1);
for (entry = tablestruct->table[hash]; entry != NULL; entry = entry->next) {
if (entry->key == key) {
return entry->value;
}
}
return NULL;
}
/* Add the key to the hash table. Assumes the key is not already present. */
int
hash_insert (struct hashtable *tablestruct, uintptr_t key, void *value)
{
uintptr_t hash;
struct hashentry *entry;
hash = hash_hash (key) & (tablestruct->size - 1);
//printf ("bucket is %d ", hash);
entry = malloc (sizeof (struct hashentry));
if (!entry) {
return -1;
}
entry->key = key;
entry->value = value;
entry->next = tablestruct->table[hash];
tablestruct->table[hash] = entry;
return 0;
}
/* Removes the key from the hash table. Does not signal an error if the key
* was not present. */
void
hash_remove (struct hashtable *tablestruct, uintptr_t key)
{
uintptr_t hash;
struct hashentry *entry, *tmpentry;
hash = hash_hash (key) & (tablestruct->size - 1);
entry = tablestruct->table[hash];
/* If this is the first entry then it needs special handling. */
if (entry && entry->key == key) {
tmpentry = entry->next;
free (entry);
tablestruct->table[hash] = tmpentry;
} else {
while (entry) {
if (entry->next && entry->next->key == key) {
tmpentry = entry->next;
entry->next = entry->next->next;
free (tmpentry);
break;
}
entry = entry->next;
}
}
}
hash_free.c
#include <stdint.h>
#include <stdlib.h>
#include "hash.h"
void
hash_free (struct hashtable *tablestruct)
{
int counter;
struct hashentry *entry, *prev;
/* Need to free buckets and table struct and every item in every chain */
for (counter=0; counter<tablestruct->size; counter++) {
entry = tablestruct->table[counter];
while (entry) {
prev = entry;
entry = entry->next;
free (prev);
}
}
free (tablestruct->table);
free (tablestruct);
}
#include <stdlib.h>
#include "hash.h"
void
hash_free (struct hashtable *tablestruct)
{
int counter;
struct hashentry *entry, *prev;
/* Need to free buckets and table struct and every item in every chain */
for (counter=0; counter<tablestruct->size; counter++) {
entry = tablestruct->table[counter];
while (entry) {
prev = entry;
entry = entry->next;
free (prev);
}
}
free (tablestruct->table);
free (tablestruct);
}
来源:http://ertos.nicta.com.au/software/kenge/libhash/devel/
更多结果:http://www.google.cn/search?complete=1&hl=zh-CN&q=libhash&meta=