[转]libhash中的哈希函数


随便贴一个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 */

 

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;
                }
        }
}

 

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);
}

 

来源:http://ertos.nicta.com.au/software/kenge/libhash/devel/

更多结果:http://www.google.cn/search?complete=1&hl=zh-CN&q=libhash&meta=

 

你可能感兴趣的:(c,struct,table,null,insert)