// File: hash.C // // Implementation of hash tables #include #include #include #include "hash.h" //======================================================================= // Functions for this file only // Determine if the given number is prime. // int IsPrime(int n) { int d, sq ; // Silly cases if (n <= 0 ) return 0 ; if (n == 1) return 1 ; if (n % 2 == 0) return 0 ; // check all numbers up to square root of n sq = sqrt(n) + 1 ; // round up in case of floating point error for (d = 3 ; d <= sq ; d++) { if (n % d == 0) return 0 ; } return 1 ; // no divisors found } // Crash if new return NULL // void CrashOnNull(void *ptr, char* mesg) { if (ptr == NULL) { fprintf(stderr, "CrashOnNull: %s\n", mesg) ; exit(1) ; } } //======================================================================= // Member functions for HashTable class // Magic Number for minimum table size // #define MIN_TSIZE 100 // Hash Table Constructor. // Note: there is no default constructor, since the size of // hash table is required. HashTable::HashTable(int size) { int i ; // Table size < MIN_TSIZE is ridiculously small if (size < MIN_TSIZE) size = MIN_TSIZE ; // Find prime number between size and 2*size. Tsize = 0 ; for (i = size ; i <= 2*size ; i++) { if (IsPrime(i)) { Tsize = i ; break ; } } // Sanity check for table size if (Tsize <= MIN_TSIZE) { fprintf(stderr, "Internal error: could not find prime table size\n") ; exit(1) ; } // Initialize data members count = 0 ; Table = new List* [Tsize] ; CrashOnNull(Table, "could not create new table") ; for (i = 0 ; i < Tsize ; i++) { Table[i] = NULL ; } } HashTable::~HashTable() { // Destructor ; int i ; for (i = 0 ; i < Tsize ; i++) { delete Table[i] ; // call List destructor } delete [] Table ; // delete array of pointers } void HashTable::Insert(const ListItem& x) { int index ; index = hash(x.ssn) ; // Hash by ssn // Create list if no list at this index if (Table[index] == NULL) { Table[index] = new List ; CrashOnNull(Table[index], "could not create new list") ; } count++ ; Table[index]->Append(x) ; } ListItem *HashTable::Find(hash_t key) { int index ; position pos ; index = hash(key) ; // Empty list means no such item if (Table[index] == NULL) return NULL ; pos = Table[index]->Locate(ListItem(key)) ; return Table[index]->ItemAt(pos) ; } void HashTable::Delete(hash_t key) { int index ; position pos ; index = hash(key) ; // Empty list means no such item if (Table[index] == NULL) return ; count-- ; pos = Table[index]->Locate(ListItem(key)) ; Table[index]->Delete(pos) ; } void HashTable::dump() { int i, c ; // Report internal constants // printf("\n\n***************Begin Dump***************\n") ; printf("HashTable: Tsize = %d, count = %d\n", Tsize, count) ; // Print out list at each non-empty index // for (i = 0 ; i < Tsize ; i++) { if (Table[i] == NULL) continue ; // skip NULL entries if (c = Table[i]->Count() != 0) { printf("\nHash Table entries at index = %d, count = %d\n", i, c) ; Table[i]->Print() ; } } printf("****************End Dump****************\n\n\n") ; } void HashTable::stats() { int c, i, max, min, sum, nz ; float avg, load ; if (count == 0) { printf("\n\nEmpty Hash Table!!!\n") ; return ; } printf("\n\n***************Begin Stats***************\n") ; printf("Table size = %d\n", Tsize) ; printf("Number of items = %d\n", count) ; load = ( (float) count) / Tsize ; printf("Load Factor = items/size = %6.4f\n", load) ; // Collect collision stats min = count + 1 ; // bigger than any list size max = 0 ; nz = 0 ; sum = 0 ; for (i = 0 ; i < Tsize ; i++) { if (Table[i] == NULL) { min = 0 ; } else { nz++ ; c = Table[i]->Count() ; if (c > max) max = c ; if (c < min) min = c ; sum = sum + c ; } } avg = ((float) sum) / Tsize ; printf("Smallest linked list length: %d\n", min) ; printf("Largest linked list length: %d\n", max) ; printf("Average linked list length: %5.2f\n", avg) ; printf("Average nubmer of collisions: %5.2f\n", ((float) sum)/nz) ; printf("\n****************End Stats****************\n\n\n") ; } int HashTable::hash(hash_t key) { long int temp ; // hash function h(x) = x % Tsize // temp = key % Tsize ; if (temp >= 0) return temp ; // Arithmetic overflow? fprintf(stderr, "Problem with negative hash index\n") ; exit(1) ; return 0 ; // make the compiler shut up }