00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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;
00032 int key;
00033 struct inthash_node_t *next;
00034 } inthash_node_t;
00035
00036
00037
00038
00039
00040
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
00055
00056
00057
00058
00059 VMDEXTERNSTATIC void inthash_init(inthash_t *tptr, int buckets) {
00060
00061
00062 if (buckets==0)
00063 buckets=16;
00064
00065
00066 tptr->entries=0;
00067 tptr->size=2;
00068 tptr->mask=1;
00069 tptr->downshift=29;
00070
00071
00072 while (tptr->size<buckets) {
00073 tptr->size<<=1;
00074 tptr->mask=(tptr->mask<<1)+1;
00075 tptr->downshift--;
00076 }
00077
00078
00079 tptr->bucket=(inthash_node_t **) calloc(tptr->size, sizeof(inthash_node_t *));
00080
00081 return;
00082 }
00083
00084
00085
00086
00087
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
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 }
00108 }
00109
00110
00111 free(old_bucket);
00112
00113 return;
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123 VMDEXTERNSTATIC int inthash_lookup(const inthash_t *tptr, int key) {
00124 int h;
00125 inthash_node_t *node;
00126
00127
00128
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
00136 return(node ? node->data : HASH_FAIL);
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
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
00153 if ((tmp=inthash_lookup(tptr, key)) != HASH_FAIL)
00154 return(tmp);
00155
00156
00157 while (tptr->entries>=HASH_LIMIT*tptr->size)
00158 rebuild_table(tptr);
00159
00160
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
00174
00175
00176
00177
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
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
00192 if (node==NULL)
00193 return HASH_FAIL;
00194
00195
00196 if (node==tptr->bucket[h])
00197 tptr->bucket[h]=node->next;
00198 else {
00199
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
00208 data=node->data;
00209 free(node);
00210
00211 return(data);
00212 }
00213
00214
00215
00216
00217
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
00234 if (tptr->bucket != NULL) {
00235 free(tptr->bucket);
00236 memset(tptr, 0, sizeof(inthash_t));
00237 }
00238 }
00239
00240
00241
00242
00243
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 }
00256
00257 return(tptr->entries ? alos/tptr->entries : 0);
00258 }
00259
00260
00261
00262
00263
00264
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