Please send questions to st10@humboldt.edu .
/************************************************************/
/* implementation of .h file adapted from                   */
/* http://www.cs.colorado.edu/~main/chapter12/table2.h      */
/*                                                          */
/* Main and Savitch, "Data Structures and Other Objects     */
/*    using C++", 2nd edition, Addison-Wesley, Ch.12, p.587 */
/************************************************************/

//-----------------------------------------------------------
// File: hashtable.template
// Name: Sharon Tuttle and (your name here)
//       (implementing an adaptation of a .h file adapted from
//       Savitch and Main)
// last modified: 4-20-05
//
// Template Class: hashtable<RecordType> (a hash table
//                 of records of type RecordType)
//
// Because this is a template class, it is included in
//    the header file, and not compiled separately.
//**************************************************************

#include "hashtable.h"
#include <iostream>
using namespace std;

/**********************************************************/
/* CONSTRUCTORS and DESTRUCTOR                            */
/**********************************************************/

// constructor
//
// postcondition: creates an empty hashtable instance
//    of table_size given_table_size.
//
template <typename RecordType>
hashtable<RecordType>::hashtable( size_t given_table_size )
{
    table_size = given_table_size;
    data = new node<RecordType>*[table_size];

    total_records = 0;

    // initialize each bucket so that it initially is NULL
    YOU FILL IN
}

// copy constructor
//
template <typename RecordType>
hashtable<RecordType>::hashtable(const hashtable<RecordType>& source)
{
    total_records = source.total_records;

    node<RecordType> *tail_ptr; // needed for argument of list_copy

    // use node's list toolkit list_copy to copy over
    //    each bucket's chain
    for (int i=0; i<table_size; i++)
    {
        list_copy(source.data[i], data[i], tail_ptr);
        tail_ptr = NULL;
    }
}

// destructor
//
template <typename RecordType>
hashtable<RecordType>::~hashtable( )
{
    // call node's list_clear toolkit function for each bucket
    YOU FILL IN
}

/*******************************************************/
/* ACCESSORS and other constant member functions       */
/*    (observers)                                      */
/*******************************************************/
        
// find
//
// postconditions: if a record is in the hashtable with
//    the specified key this_key, then found is set to
//    true and result is set to a copy of the record
//    with that key. Otherwise found is false and the
//    result contains garbage.
//
template <typename RecordType>
void hashtable<RecordType>::find(int this_key, bool& found,
     RecordType& result) const
{
    size_t index;

    // where should record with this_key be?
    YOU FILL IN

    node<RecordType> *curr;

    curr = data[index];

    YOU FILL IN THE REST
}
    
// is_present
//
// postcondition: returns true if there is a record
//    in the hashtable with key of this_key. Othewise,
//    returns false.
//
template <typename RecordType>
bool hashtable<RecordType>::is_present(int this_key) const
{
    size_t index;

    // where should this_key's record be?
    YOU FILL IN

    node<RecordType> *curr;

    YOU FILL IN THE REST
}

// size
//
// postcondition: returns the total number of records
//    in the hashtable.
//
template <typename RecordType>
size_t hashtable<RecordType>::get_size( ) const
{
    return total_records;
}
        

// print_hashtable
//
// postcondition: prints the keys within non-empty
//    buckets, 1 non-empty bucket per line
//
template <typename RecordType>
void hashtable<RecordType>::print_hashtable( ) const
{
    node<RecordType> *curr;

    cout << "printing non-empty buckets of hash table: " << endl;
    cout << "-----------------------------------------" << endl;

    for (int i=0; i<table_size; i++)
    {
        if (data[i] != NULL)
        {
            cout << "bucket[" << i << "]: ";
      
            curr = data[i];

            // while haven't reached end of chain, print 
            //    key of current record in chain
            YOU FILL IN

            cout << endl;
        }
    }

    cout << endl;
}

/****************************************************/
/* MODIFIERS and other modifying member functions   */
/****************************************************/

// insert
//
// preconditions: entry.get_key( ) >= 0. Also, if 
//    entry.get_key( ) is not already a key in the
//    hashtable, then the hashtable has space for another
//    record (haven't exceeded free store...)
// postconditions: if the table already had a record
//    with key equal to entry.get_key( ), then that record
//    is replaced by entry. Otherwise, entry has been
//    added as a new record of the hashtable.
//
template <typename RecordType>
void hashtable<RecordType>::insert(const RecordType& entry)
{
    size_t index;

    // find out where this entry should go
    YOU FILL IN

    // IF this key is NOT already in the hashtable --- where
    //    should it go? Put it there.
    YOU FILL IN

    // ELSE replace key's current entry with this new entry 
    else
    {
        node<RecordType> *curr;

        // we KNOW key is HERE, or we wouldn't have reached here!
        //    (else clause for !is_present(key) )
        YOU FILL IN THE REST
    }
}

// remove
//
// postconditions: if a record was in the hashtable with
//    the specified key this_key, then that record has 
//    been removed; otherwise the hashtable is unchanged.
//
template <typename RecordType>
void hashtable<RecordType>::remove(int this_key)
{
    size_t index;

    // where should this_key's entry be?
    YOU FILL IN

    node<RecordType> *curr;
    node<RecordType> *prev = NULL;

    // point to chain where element would be...
    YOU FILL IN

    // if element is head of a non-null chain...
    YOU FILL IN

    // else...
    YOU FILL IN
}

/********************************************************/
/* overloaded operators                                 */
/********************************************************/

// =
//
// postcondition: the hashtable that activated this
//    will be made to have the same records as source
//
template <typename RecordType>
void hashtable<RecordType>::operator =(
     const hashtable<RecordType>& source)
{
    node<RecordType> *tail_ptr;

    if (this == &source)
    {
        return;
    }

    for (int i=0; i<table_size; i++)
    {
        list_clear(data[i]);

        list_copy(source.data[i], data[i], tail_ptr);
        tail_ptr = NULL;
    }
    total_records = source.total_records;
}

/****************************************************/
/* PRIVATE HELPER MEMBER FUNCTIONS                  */
/****************************************************/

// hash
//
// postconditions: returns a number in the range
//    [0, table_size) based on key this_key.
//
template <typename RecordType>
size_t hashtable<RecordType>::hash(int this_key) const
{
    return this_key % table_size;
}