Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

inthash.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2011 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: inthash.c,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.6 $      $Date: 2010/12/16 04:08:55 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   A simple hash table implementation for ints, contributed by John Stone,
00019  *   derived from his ray tracer code.
00020  ***************************************************************************/
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include "inthash.h"
00026 
00027 #define HASH_LIMIT 0.5
00028 
00030 typedef struct inthash_node_t {
00031   int data;                           /* data in hash node */
00032   int key;                            /* key for hash lookup */
00033   struct inthash_node_t *next;        /* next node in hash chain */
00034 } inthash_node_t;
00035 
00036 /*
00037  *  inthash() - Hash function returns a hash number for a given key.
00038  *
00039  *  tptr: Pointer to a hash table
00040  *  key: The key to create a hash number for
00041  */
00042 static int inthash(const inthash_t *tptr, int key) {
00043   int hashvalue;
00044 
00045   hashvalue = (((key*1103515249)>>tptr->downshift) & tptr->mask);
00046   if (hashvalue < 0) {
00047     hashvalue = 0;
00048   }    
00049 
00050   return hashvalue;
00051 }
00052 
00053 /*
00054  *  inthash_init() - Initialize a new hash table.
00055  *
00056  *  tptr: Pointer to the hash table to initialize
00057  *  buckets: The number of initial buckets to create
00058  */
00059 VMDEXTERNSTATIC void inthash_init(inthash_t *tptr, int buckets) {
00060 
00061   /* make sure we allocate something */
00062   if (buckets==0)
00063     buckets=16;
00064 
00065   /* initialize the table */
00066   tptr->entries=0;
00067   tptr->size=2;
00068   tptr->mask=1;
00069   tptr->downshift=29;
00070 
00071   /* ensure buckets is a power of 2 */
00072   while (tptr->size<buckets) {
00073     tptr->size<<=1;
00074     tptr->mask=(tptr->mask<<1)+1;
00075     tptr->downshift--;
00076   } /* while */
00077 
00078   /* allocate memory for table */
00079   tptr->bucket=(inthash_node_t **) calloc(tptr->size, sizeof(inthash_node_t *));
00080 
00081   return;
00082 }
00083 
00084 /*
00085  *  rebuild_table() - Create new hash table when old one fills up.
00086  *
00087  *  tptr: Pointer to a hash table
00088  */
00089 static void rebuild_table(inthash_t *tptr) {
00090   inthash_node_t **old_bucket, *old_hash, *tmp;
00091   int old_size, h, i;
00092 
00093   old_bucket=tptr->bucket;
00094   old_size=tptr->size;
00095 
00096   /* create a new table and rehash old buckets */
00097   inthash_init(tptr, old_size<<1);
00098   for (i=0; i<old_size; i++) {
00099     old_hash=old_bucket[i];
00100     while(old_hash) {
00101       tmp=old_hash;
00102       old_hash=old_hash->next;
00103       h=inthash(tptr, tmp->key);
00104       tmp->next=tptr->bucket[h];
00105       tptr->bucket[h]=tmp;
00106       tptr->entries++;
00107     } /* while */
00108   } /* for */
00109 
00110   /* free memory used by old table */
00111   free(old_bucket);
00112 
00113   return;
00114 }
00115 
00116 /*
00117  *  inthash_lookup() - Lookup an entry in the hash table and return a pointer to
00118  *    it or HASH_FAIL if it wasn't found.
00119  *
00120  *  tptr: Pointer to the hash table
00121  *  key: The key to lookup
00122  */
00123 VMDEXTERNSTATIC int inthash_lookup(const inthash_t *tptr, int key) {
00124   int h;
00125   inthash_node_t *node;
00126 
00127 
00128   /* find the entry in the hash table */
00129   h=inthash(tptr, key);
00130   for (node=tptr->bucket[h]; node!=NULL; node=node->next) {
00131     if (node->key == key)
00132       break;
00133   }
00134 
00135   /* return the entry if it exists, or HASH_FAIL */
00136   return(node ? node->data : HASH_FAIL);
00137 }
00138 
00139 /*
00140  *  inthash_insert() - Insert an entry into the hash table.  If the entry already
00141  *  exists return a pointer to it, otherwise return HASH_FAIL.
00142  *
00143  *  tptr: A pointer to the hash table
00144  *  key: The key to insert into the hash table
00145  *  data: A pointer to the data to insert into the hash table
00146  */
00147 VMDEXTERNSTATIC int inthash_insert(inthash_t *tptr, int key, int data) {
00148   int tmp;
00149   inthash_node_t *node;
00150   int h;
00151 
00152   /* check to see if the entry exists */
00153   if ((tmp=inthash_lookup(tptr, key)) != HASH_FAIL)
00154     return(tmp);
00155 
00156   /* expand the table if needed */
00157   while (tptr->entries>=HASH_LIMIT*tptr->size)
00158     rebuild_table(tptr);
00159 
00160   /* insert the new entry */
00161   h=inthash(tptr, key);
00162   node=(struct inthash_node_t *) malloc(sizeof(inthash_node_t));
00163   node->data=data;
00164   node->key=key;
00165   node->next=tptr->bucket[h];
00166   tptr->bucket[h]=node;
00167   tptr->entries++;
00168 
00169   return HASH_FAIL;
00170 }
00171 
00172 /*
00173  *  inthash_delete() - Remove an entry from a hash table and return a pointer
00174  *  to its data or HASH_FAIL if it wasn't found.
00175  *
00176  *  tptr: A pointer to the hash table
00177  *  key: The key to remove from the hash table
00178  */
00179 VMDEXTERNSTATIC int inthash_delete(inthash_t *tptr, int key) {
00180   inthash_node_t *node, *last;
00181   int data;
00182   int h;
00183 
00184   /* find the node to remove */
00185   h=inthash(tptr, key);
00186   for (node=tptr->bucket[h]; node; node=node->next) {
00187     if (node->key == key)
00188       break;
00189   }
00190 
00191   /* Didn't find anything, return HASH_FAIL */
00192   if (node==NULL)
00193     return HASH_FAIL;
00194 
00195   /* if node is at head of bucket, we have it easy */
00196   if (node==tptr->bucket[h])
00197     tptr->bucket[h]=node->next;
00198   else {
00199     /* find the node before the node we want to remove */
00200     for (last=tptr->bucket[h]; last && last->next; last=last->next) {
00201       if (last->next==node)
00202         break;
00203     }
00204     last->next=node->next;
00205   }
00206 
00207   /* free memory and return the data */
00208   data=node->data;
00209   free(node);
00210 
00211   return(data);
00212 }
00213 
00214 
00215 
00216 /*
00217  * inthash_destroy() - Delete the entire table, and all remaining entries.
00218  * 
00219  */
00220 VMDEXTERNSTATIC void inthash_destroy(inthash_t *tptr) {
00221   inthash_node_t *node, *last;
00222   int i;
00223 
00224   for (i=0; i<tptr->size; i++) {
00225     node = tptr->bucket[i];
00226     while (node != NULL) { 
00227       last = node;   
00228       node = node->next;
00229       free(last);
00230     }
00231   }     
00232 
00233   /* free the entire array of buckets */
00234   if (tptr->bucket != NULL) {
00235     free(tptr->bucket);
00236     memset(tptr, 0, sizeof(inthash_t));
00237   }
00238 }
00239 
00240 /*
00241  *  alos() - Find the average length of search.
00242  *
00243  *  tptr: Pointer to a hash table
00244  */
00245 static float alos(inthash_t *tptr) {
00246   int i,j;
00247   float alos=0;
00248   inthash_node_t *node;
00249 
00250 
00251   for (i=0; i<tptr->size; i++) {
00252     for (node=tptr->bucket[i], j=0; node!=NULL; node=node->next, j++);
00253     if (j)
00254       alos+=((j*(j+1))>>1);
00255   } /* for */
00256 
00257   return(tptr->entries ? alos/tptr->entries : 0);
00258 }
00259 
00260 
00261 /*
00262  *  inthash_stats() - Return a string with stats about a hash table.
00263  *
00264  *  tptr: A pointer to the hash table
00265  */
00266 VMDEXTERNSTATIC char * inthash_stats(inthash_t *tptr) {
00267   static char buf[1024];
00268 
00269   sprintf(buf, "%u slots, %u entries, and %1.2f ALOS",
00270     (int)tptr->size, (int)tptr->entries, alos(tptr));
00271 
00272   return(buf);
00273 }
00274 
00275 
00276 
00277 

Generated on Thu May 23 01:47:33 2013 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002