/**************************************************************************/ /* hashtable.h: definition of a hashtable over long integer values */ /* The hashtable only saves one key, no value can be associated */ /* */ /* Thorsten Brehm, 4/2001 */ /**************************************************************************/ #include #include #include "hashtable.h" HashTable* newHashTable(unsigned long size) { HashTable* h = (HashTable*) calloc(1,sizeof(HashTable)); if (h!=NULL) { h->hashArray = (HashElement**) calloc(size,sizeof(HashElement*)); if (h->hashArray!=NULL) { h->size = size; h->rehashAt = h->size-(h->size/10); // rehash at 90% h->incrementSize = size; h->count = 0; h->outOfMemory=0; } else { free(h); h=NULL; } } return h; } void freeHashTable(HashTable* h) { int i=0; HashElement *e,*p; while (isize) { e=h->hashArray[i]; while (e) { p=e; e=e->next; free(p); } i++; } free(h->hashArray); free(h); } HashElement* newHashElement(FileOffset value) { HashElement* e = (HashElement*) malloc(sizeof(HashElement)); e->value = value; e->next = NULL; return e; } void freeHashElement(HashElement* e) { free(e); } void rehash(HashTable* h) { if (h->outOfMemory==0) { HashTable* h2 = newHashTable(h->size+h->incrementSize); HashElement *e,*l; unsigned long sz,hash,i=0; if (h2==NULL) { h->outOfMemory=1; } else { sz=h2->size; // make increment of new table same as old h2->incrementSize=h->incrementSize; while (isize) { l = h->hashArray[i]; // get list from old hash table h->hashArray[i]=NULL; while (l!=NULL) { // process every entry from old list e = l; // process first list element l = l->next; // get the tail of the list // hash value for entry to be processed hash = ((unsigned long) e->value) % sz; e->next = h2->hashArray[hash]; // append entries to new list h2->hashArray[hash]=e; // set list in new hash table } i++; } // swap old and new hash table (to keep pointers to old table valid!) l=(HashElement*) h->hashArray; // move new hashArray to old hashTable h->hashArray = h2->hashArray; // set temporary hashTable to old hashArray h2->hashArray= (HashElement**)l; h2->size = h->size; // set temporary hashTable size to old size h->size = sz; // set hash table size to new size h->rehashAt = h->size-(h->size/10); // set new rehash size: 90% // get rid of temporary table, now holding old hashArray freeHashTable(h2); } } } void addToHashTable (HashTable* h, FileOffset value) { unsigned long hash = value % h->size; HashElement* e = newHashElement(value); e->next = h->hashArray[hash]; h->hashArray[hash]=e; if (h->count++>h->rehashAt) rehash(h); } void removeFromHashTable (HashTable* h,FileOffset value) { unsigned long hash = value % h->size; HashElement* e = h->hashArray[hash]; HashElement* l = NULL; while (e!=NULL) { if (e->value==value) { if (l==NULL) { h->hashArray[hash]=e->next; e->next = NULL; freeHashElement(e); e = h->hashArray[hash]; } else { l->next=e->next; e->next = NULL; freeHashElement(e); e=l->next; } } else { l=e; e=e->next; } } } //#define showHashStatistic int isInHashTable(HashTable* h, FileOffset value) { unsigned long hash = value % h->size; HashElement *e = h->hashArray[hash]; #ifdef showHashStatistic int c=0; while ((e!=NULL)&&(e->value!=value)) {e=e->next;c++;} if (c>5) printf("needed: %i, size: %i\n",c,h->count); #else while ((e!=NULL)&&(e->value!=value)) e=e->next; #endif return (e!=NULL); }