#include "QuadraticProbing.h" #include /** * Internal method to test if a positive number is prime. * Not an efficient algorithm. */ bool isPrime( int n ) { if( n == 2 || n == 3 ) return true; if( n == 1 || n % 2 == 0 ) return false; for( int i = 3; i * i <= n; i += 2 ) if( n % i == 0 ) return false; return true; } /** * Internal method to return a prime number at least as large as n. * Assumes n > 0. */ int nextPrime( int n ) { if( n % 2 == 0 ) n++; for( ; !isPrime( n ); n += 2 ) ; return n; } /** * Construct the hash table. */ template HashTable::HashTable( const HashedObj & notFound, int size ) : ITEM_NOT_FOUND( notFound ), array( nextPrime( size ) ) { makeEmpty( ); } /** * Insert item x into the hash table. If the item is * already present, then do nothing. */ template void HashTable::insert( const HashedObj & x ) { // Insert x as active int currentPos = findPos( x ); if( isActive( currentPos ) ) return; if( array[ currentPos ].info != DELETED ) ++currentSize; array[ currentPos ] = HashEntry( x, ACTIVE ); // Rehash; see Section 5.5 if( currentSize > array.size( ) / 2 ) rehash( ); } /** * Expand the hash table. */ template void HashTable::rehash( ) { vector oldArray = array; // Create new double-sized, empty table array.resize( nextPrime( 2 * oldArray.size( ) ) ); for( int j = 0; j < array.size( ); j++ ) array[ j ].info = EMPTY; // Copy table over currentSize = 0; for( int i = 0; i < oldArray.size( ); i++ ) if( oldArray[ i ].info == ACTIVE ) insert( oldArray[ i ].element ); } /** * Method that performs quadratic probing resolution. * Return the position where the search for x terminates. */ template int HashTable::findPos( const HashedObj & x ) const { /* 1*/ int collisionNum = 0; /* 2*/ int currentPos = hash( x, array.size( ) ); /* 3*/ while( array[ currentPos ].info != EMPTY && array[ currentPos ].element != x ) { /* 4*/ currentPos += 2 * ++collisionNum - 1; // Compute ith probe /* 5*/ if( currentPos >= array.size( ) ) /* 6*/ currentPos -= array.size( ); } /* 7*/ return currentPos; } /** * Remove item x from the hash table. */ template void HashTable::remove( const HashedObj & x ) { int currentPos = findPos( x ); if( isActive( currentPos ) ) array[ currentPos ].info = DELETED; } /** * Find item x in the hash table. * Return the matching item or ITEM_NOT_FOUND if not found */ template const HashedObj & HashTable::find( const HashedObj & x ) const { int currentPos = findPos( x ); if( isActive( currentPos ) ) return array[ currentPos ].element; else return ITEM_NOT_FOUND; } /** * Make the hash table logically empty. */ template void HashTable::makeEmpty( ) { currentSize = 0; for( int i = 0; i < array.size( ); i++ ) array[ i ].info = EMPTY; } /** * Deep copy. */ template const HashTable & HashTable:: operator=( const HashTable & rhs ) { if( this != &rhs ) { array = rhs.array; currentSize = rhs.currentSize; } return *this; } /** * Return true if currentPos exists and is active. */ template bool HashTable::isActive( int currentPos ) const { return array[ currentPos ].info == ACTIVE; } /** * A hash routine for string objects. */ int hash( const string & key, int tableSize ) { int hashVal = 0; for( int i = 0; i < key.length( ); i++ ) hashVal = 37 * hashVal + key[ i ]; hashVal %= tableSize; if( hashVal < 0 ) hashVal += tableSize; return hashVal; } /** * A hash routine for ints. */ int hash( int key, int tableSize ) { if( key < 0 ) key = -key; return key % tableSize; }