// File: hash.C // // Implementation of a hash table of student records #include #include #include #include #include "hash.h" //======================================================================= // Functions for this file only // Determine if the given number is prime. // static int IsPrime(int n) ; static 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 } //======================================================================= // 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) { cerr << "Internal error: could not find prime table size" << endl ; exit(1) ; } // Initialize data members count = 0 ; table = new StudentList[tsize] ; } HashTable::~HashTable() { // Destructor ; delete [] table ; // delete array of pointers } void HashTable::insert(const StudentRecord& x) { int index ; index = hash(x.ssn) ; // Hash by ssn count++ ; table[index].append(x) ; } bool HashTable::find(hash_t key, StudentRecord& rec) { int index ; StudentRecord data ; index = hash(key) ; if (table[index].length() == 0) return false ; SLIterator it(table[index]) ; // initialize iterator while (it.next(data)) { if (data.ssn == key) { rec = data ; return true ; } } return false ; } int HashTable::extract(hash_t key) { int index, num ; index = hash(key) ; num = table[index].remove(key) ; count = count - num ; return num ; // number of items removed } void HashTable::dump() { int i, c, len ; // Report internal constants // cout << "\n\n***************Begin Dump***************\n" ; cout << "HashTable: tsize = " << tsize << ", count = " << count << endl ; // Print out list at each non-empty index // for (i = 0 ; i < tsize ; i++) { if (len = table[i].length() != 0) { cout << "\nHash Table entries at index=" << i << ", length=" << len << endl ; table[i].print() ; } } cout << "****************End Dump****************\n\n" << endl ; } void HashTable::stats() { int c, i, max, min, sum, nz ; float avg, load ; if (count == 0) { cout << "\n\nEmpty Hash Table!!!" << endl ; return ; } cout << "\n\n***************Begin Stats***************\n" ; cout << "Table size = " << tsize << endl ; cout << "Number of items = " << count << endl ; load = ( (float) count) / tsize ; cout << "Load Factor = items/size = " << load << endl ; // 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].length() == 0) { min = 0 ; } else { nz++ ; c = table[i].length() ; if (c > max) max = c ; if (c < min) min = c ; sum = sum + c ; } } avg = ((float) sum) / tsize ; cout << "Smallest linked list length: " << min << endl ; cout << "Largest linked list length: " << max << endl ; cout << "Average linked list length: " << avg << endl ; cout << "Average nubmer of collisions: " << ((float) sum)/nz << endl ; cout << "\n****************End Stats****************\n\n" << endl ; } 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? cerr << "Problem with negative hash index" << endl ; exit(1) ; return 0 ; // make the compiler shut up }