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;
}