Please send questions to st10@humboldt.edu .
/************************************************************/
/* ADAPTED FROM:                                            */
/* http://www.cs.colorado.edu/~main/chapter4/bag2.cxx       */
/*                                                          */
/* Main and Savitch, "Data Structures and Other Objects     */
/*    using C++", 2nd edition, Addison-Wesley, Ch.4,        */
/*    pp. 178-180 (mostly)                                  */
/************************************************************/

//-----------------------------------------------------------
// File: set.cpp
// Name: Michael Main, Walter Savitch
//       (adapted by Sharon M. Tuttle)
// last modified: 3-10-04
//
// Class implemented: set (see set.h for documentation)
//                    (a container clas for a collection of 
//                     items with NO duplicates)
//
// INVARIANT for the set class:
//   1. The number of items in the set is in the 
//      member variable used;
//   2. The actual items of the set are stored in a partially 
//      filled array. The array is a dynamic array, pointed to 
//      by the member variable data;
//   3. The size of the dynamic array is in the member 
//      variable capacity.
//--------------------------------------------------------------

#include <algorithm>     // Provides copy function
#include <cassert>       // Provides assert function
#include "set.h"
using namespace std;

// (note that the following is required for the named constant)

const set::size_type set::DEFAULT_CAPACITY;

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

set::set()
{
    data = new value_type[DEFAULT_CAPACITY];
    capacity = DEFAULT_CAPACITY;
    used = 0;
}

set::set(size_type initial_capacity)
{
    data = new value_type[initial_capacity];
    capacity = initial_capacity;
    used = 0;
}

// Copy constructor
//
// Library facilities used: algorithm
//
set::set(const set& source)
{
    data = new value_type[source.capacity];
    capacity = source.capacity;
    used = source.used;

    // (copy is from the algorithm library)
    copy(source.data, source.data + used, data);
}

// Destructor
//
set::~set( )
{
    delete [ ] data;
}

/*************************************************************/
/* ACCESSORS and other constant member functions (observers) */
/*************************************************************/

// size was already implemented in the set.h file...!

// contains
//
bool set::contains(const value_type& target) const
{
    size_type i;

    // check each item of set, seeing if it is the target;
    //    (if it is, we are DONE, the set DOES contain the
    //    target!)
    for (i = 0; i < used; i++)
    {
        if (target == data[i])
        {
            return true;
        }
    }

    // IF reach here, target was not found in set
    //    (otherwise, we would have returned from inside
    //    the loop)
    return false;
}

// capacity was already implemented in the set.h file...!

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

// insert
//
void set::insert(const value_type& entry)
{   
    // if entry is already in the set, we're done;
    //    no change is required.
    if (contains(entry))
    {
        return;
    }

    // IF reach here, entry is NOT in set, and should be
    //    added.

    // increase set's capacity if necessary
    if (used == capacity)
    {
        reserve(used+1);
    }

    data[used] = entry;
    used++;
}

// remove
//
bool set::remove(const value_type& target)
{
    size_type index; // The location of target in the data array    

    // First, set index to the location of target in the data 
    //    array, which could be as small as 0 or as large as used-1.
    //    If target is not in the array, then index will be set 
    //    equal to used.
    index = 0;
        
    while ((index < used) && (data[index] != target))
    {
        index++;
    }

    // if target isn't in the set, then there's no work to do
    if (index == used) 
    {
        return false;
    }
        
    // IF execution reaches here, target is in the set at 
    //    data[index]. So, reduce used by 1 and copy the 
    //    last item onto data[index].
    used--;
    data[index] = data[used];
    return true;
}

// reserve
//
// Library facilities used: algorithm
//
void set::reserve(size_type new_capacity)
{
    value_type *larger_array;

    // if allocated memory is already the right size, we're done;
    if (new_capacity == capacity)
    {
        return; 
    }

    // WILL let capacity of set be reduced, but NOT
    //    any smaller than current number of items.
    if (new_capacity < used)
    {
        // can't allocate less than we are using
        new_capacity = used;
    }

    // allocate new array and copy over set items
    larger_array = new value_type[new_capacity];
    copy(data, data + used, larger_array); // from algorithm library

    // (notice that we are freeing the "old" array...)
    delete [ ] data;

    data = larger_array;
    capacity = new_capacity;
}

/****************************************************/
/* OVERLOADED OPERATORS                             */
/****************************************************/

// +=
//
// Library facilities used: algorithm
void set::operator +=(const set& addend)
{
    size_t i;

    // increase set capacity if necessary
    if (used + addend.used > capacity)
    {
        reserve(used + addend.used);
    }
        
    // should ONLY add addend items to set if they
    //    are not already there; but operation insert
    //    DOES check for this (and it will update used
    //    appropriately, too! 8-) )
    for (i=0; i<addend.used; i++)
    {
        insert(addend.data[i]);
    }
}

// =
//
// Library facilities used: algorithm
//
void set::operator =(const set& source)
{
    value_type *new_data;

    // Check for possible self-assignment:
    if (this == &source)
    {
        return;
    }

    // If needed, allocate an array with a different size:
    if (capacity != source.capacity)
    { 
        new_data = new value_type[source.capacity];
        delete [ ] data;
        data = new_data;
        capacity = source.capacity;
    }

    // Copy the data from the source array:
    used = source.used;
    copy(source.data, source.data + used, data); // from algorithm lib
}

/*************************************************/
/* NONMEMBER FUNCTIONS for the set class         */
/*************************************************/
    
// slick: just implement nonmember + here!
// (how can you tell it isn't a member?
//    ...no set:: !)

set operator +(const set& s1, const set& s2)
{
    set answer(s1.size() + s2.size());

    answer += s1; 
    answer += s2;
    return answer;
}