00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include "inthash.h"
00029
00030 #define HASH_LIMIT 0.5
00031
00033 typedef struct inthash_node_t {
00034 int data;
00035 int key;
00036 struct inthash_node_t *next;
00037 } inthash_node_t;
00038
00039
00040
00041
00042
00043
00044
00045 static int inthash(const inthash_t *tptr, int key) {
00046 int hashvalue;
00047
00048 hashvalue = (((key*1103515249)>>tptr->downshift) & tptr->mask);
00049 if (hashvalue < 0) {
00050 hashvalue = 0;
00051 }
00052
00053 return hashvalue;
00054 }
00055
00056
00057
00058
00059
00060
00061
00062 VMDEXTERNSTATIC void inthash_init(inthash_t *tptr, int buckets) {
00063
00064
00065 if (buckets==0)
00066 buckets=16;
00067
00068
00069 tptr->entries=0;
00070 tptr->size=2;
00071 tptr->mask=1;
00072 tptr->downshift=29;
00073
00074
00075 while (tptr->size<buckets) {
00076 tptr->size<<=1;
00077 tptr->mask=(tptr->mask<<1)+1;
00078 tptr->downshift--;
00079 }
00080
00081
00082 tptr->bucket=(inthash_node_t **) calloc(tptr->size, sizeof(inthash_node_t *));
00083
00084 return;
00085 }
00086
00087
00088
00089
00090
00091
00092 static void rebuild_table_int(inthash_t *tptr) {
00093 inthash_node_t **old_bucket, *old_hash, *tmp;
00094 int old_size, h, i;
00095
00096 old_bucket=tptr->bucket;
00097 old_size=tptr->size;
00098
00099
00100 inthash_init(tptr, old_size<<1);
00101 for (i=0; i<old_size; i++) {
00102 old_hash=old_bucket[i];
00103 while(old_hash) {
00104 tmp=old_hash;
00105 old_hash=old_hash->next;
00106 h=inthash(tptr, tmp->key);
00107 tmp->next=tptr->bucket[h];
00108 tptr->bucket[h]=tmp;
00109 tptr->entries++;
00110 }
00111 }
00112
00113
00114 free(old_bucket);
00115
00116 return;
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126 VMDEXTERNSTATIC int inthash_lookup(const inthash_t *tptr, int key) {
00127 int h;
00128 inthash_node_t *node;
00129
00130
00131
00132 h=inthash(tptr, key);
00133 for (node=tptr->bucket[h]; node!=NULL; node=node->next) {
00134 if (node->key == key)
00135 break;
00136 }
00137
00138
00139 return(node ? node->data : HASH_FAIL);
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 VMDEXTERNSTATIC int inthash_insert(inthash_t *tptr, int key, int data) {
00151 int tmp;
00152 inthash_node_t *node;
00153 int h;
00154
00155
00156 if ((tmp=inthash_lookup(tptr, key)) != HASH_FAIL)
00157 return(tmp);
00158
00159
00160 while (tptr->entries>=HASH_LIMIT*tptr->size)
00161 rebuild_table_int(tptr);
00162
00163
00164 h=inthash(tptr, key);
00165 node=(struct inthash_node_t *) malloc(sizeof(inthash_node_t));
00166 node->data=data;
00167 node->key=key;
00168 node->next=tptr->bucket[h];
00169 tptr->bucket[h]=node;
00170 tptr->entries++;
00171
00172 return HASH_FAIL;
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182 VMDEXTERNSTATIC int inthash_delete(inthash_t *tptr, int key) {
00183 inthash_node_t *node, *last;
00184 int data;
00185 int h;
00186
00187
00188 h=inthash(tptr, key);
00189 for (node=tptr->bucket[h]; node; node=node->next) {
00190 if (node->key == key)
00191 break;
00192 }
00193
00194
00195 if (node==NULL)
00196 return HASH_FAIL;
00197
00198
00199 if (node==tptr->bucket[h])
00200 tptr->bucket[h]=node->next;
00201 else {
00202
00203 for (last=tptr->bucket[h]; last && last->next; last=last->next) {
00204 if (last->next==node)
00205 break;
00206 }
00207 last->next=node->next;
00208 }
00209
00210
00211 data=node->data;
00212 free(node);
00213
00214 return(data);
00215 }
00216
00217
00218
00219
00220
00221
00222 VMDEXTERNSTATIC int inthash_entries(inthash_t *tptr) {
00223 return tptr->entries;
00224 }
00225
00226
00227
00228
00229
00230
00231 VMDEXTERNSTATIC void inthash_destroy(inthash_t *tptr) {
00232 inthash_node_t *node, *last;
00233 int i;
00234
00235 for (i=0; i<tptr->size; i++) {
00236 node = tptr->bucket[i];
00237 while (node != NULL) {
00238 last = node;
00239 node = node->next;
00240 free(last);
00241 }
00242 }
00243
00244
00245 if (tptr->bucket != NULL) {
00246 free(tptr->bucket);
00247 memset(tptr, 0, sizeof(inthash_t));
00248 }
00249 }
00250
00251
00252
00253
00254
00255
00256 static float alos_int(inthash_t *tptr) {
00257 int i,j;
00258 float alos_int=0;
00259 inthash_node_t *node;
00260
00261
00262 for (i=0; i<tptr->size; i++) {
00263 for (node=tptr->bucket[i], j=0; node!=NULL; node=node->next, j++);
00264 if (j)
00265 alos_int+=((j*(j+1))>>1);
00266 }
00267
00268 return(tptr->entries ? alos_int/tptr->entries : 0);
00269 }
00270
00271
00272
00273
00274
00275
00276
00277 VMDEXTERNSTATIC char * inthash_stats(inthash_t *tptr) {
00278 static char buf[1024];
00279
00280 sprintf(buf, "%u slots, %u entries, and %1.2f ALOS",
00281 (int)tptr->size, (int)tptr->entries, alos_int(tptr));
00282
00283 return(buf);
00284 }
00285
00286
00287
00288