/* * File: set.h * ----------- * This file exports the Set class, which implements a * collection for storing a set of distinct elements. */ #ifndef _set_h #define _set_h #include #include "foreach.h" #include "map.h" #include "vector.h" /* * Class: Set * --------------------- * This class stores a collection of distinct elements. */ template class Set { public: /* * Constructor: Set * Usage: Set set; * -------------------------- * Creates an empty set of the specified element type. */ Set(); /* * Destructor: ~Set * ---------------- * Frees any heap storage associated with this set. */ virtual ~Set(); /* * Method: size * Usage: count = set.size(); * -------------------------- * Returns the number of elements in this set. */ int size() const; /* * Method: isEmpty * Usage: if (set.isEmpty()) ... * ----------------------------- * Returns true if this set contains no elements. */ bool isEmpty() const; /* * Method: add * Usage: set.add(value); * ---------------------- * Adds an element to this set, if it was not already there. For * compatibility with the STL set class, this method * is also exported as insert. */ void add(const ValueType & value); void insert(const ValueType & value); /* * Method: remove * Usage: set.remove(value); * ------------------------- * Removes an element from this set. If the value was not * contained in the set, no error is generated and the set * remains unchanged. */ void remove(const ValueType & value); /* * Method: contains * Usage: if (set.contains(value)) ... * ----------------------------------- * Returns true if the specified value is in this set. */ bool contains(const ValueType & value) const; /* * Method: isSubsetOf * Usage: if (set.isSubsetOf(set2)) ... * ------------------------------------ * Implements the subset relation on sets. It returns * true if every element of this set is * contained in set2. */ bool isSubsetOf(const Set & set2) const; /* * Method: clear * Usage: set.clear(); * ------------------- * Removes all elements from this set. */ void clear(); /* * Operator: == * Usage: set1 == set2 * ------------------- * Returns true if set1 and set2 * contain the same elements. */ bool operator==(const Set & set2) const; /* * Operator: != * Usage: set1 != set2 * ------------------- * Returns true if set1 and set2 * are different. */ bool operator!=(const Set & set2) const; /* * Operator: + * Usage: set1 + set2 * set1 + element * --------------------- * Returns the union of sets set1 and set2, which * is the set of elements that appear in at least one of the two sets. The * right hand set can be replaced by an element of the value type, in which * case the operator returns a new set formed by adding that element. */ Set operator+(const Set & set2) const; Set operator+(const ValueType & element) const; /* * Operator: * * Usage: set1 * set2 * ------------------ * Returns the intersection of sets set1 and set2, * which is the set of all elements that appear in both. */ Set operator*(const Set & set2) const; /* * Operator: - * Usage: set1 - set2 * set1 - element * --------------------- * Returns the difference of sets set1 and set2, * which is all of the elements that appear in set1 but * not set2. The right hand set can be replaced by an * element of the value type, in which case the operator returns a new * set formed by removing that element. */ Set operator-(const Set & set2) const; Set operator-(const ValueType & element) const; /* * Operator: += * Usage: set1 += set2; * set1 += value; * --------------------- * Adds all of the elements from set2 (or the single * specified value) to set1. As a convenience, the * Set package also overloads the comma operator so * that it is possible to initialize a set like this: * *
 *    Set digits;
 *    digits += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
 *
*/ Set & operator+=(const Set & set2); Set & operator+=(const ValueType & value); /* * Operator: *= * Usage: set1 *= set2; * -------------------- * Removes any elements from set1 that are not present in * set2. */ Set & operator*=(const Set & set2); /* * Operator: -= * Usage: set1 -= set2; * set1 -= value; * --------------------- * Removes the elements from set2 (or the single * specified value) from set1. As a convenience, the * Set package also overloads the comma operator so * that it is possible to remove multiple elements from a set * like this: * *
 *    digits -= 0, 2, 4, 6, 8;
 *
* * which removes the values 0, 2, 4, 6, and 8 from the set * digits. */ Set & operator-=(const Set & set2); Set & operator-=(const ValueType & value); /* * Method: first * Usage: ValueType value = set.first(); * ------------------------------------- * Returns the first value in the set in the order established by the * foreach macro. If the set is empty, first * generates an error. */ ValueType first() const; /* * Method: toString * Usage: string str = set.toString(); * ----------------------------------- * Converts the set to a printable string representation. */ std::string toString(); /* * Method: mapAll * Usage: set.mapAll(fn); * ---------------------- * Iterates through the elements of the set and calls fn(value) * for each one. The values are processed in ascending order, as defined * by the comparison function. */ void mapAll(void (*fn)(ValueType)) const; void mapAll(void (*fn)(const ValueType &)) const; template void mapAll(FunctorType fn) const; /* * Additional Set operations * ------------------------- * In addition to the methods listed in this interface, the Set class * supports the following operations: * * - Stream I/O using the << and >> operators * - Deep copying for the copy constructor and assignment operator * - Iteration using the range-based for statement and STL iterators * * The iteration forms process the Set in ascending order. */ /* Private section */ /**********************************************************************/ /* Note: Everything below this point in the file is logically part */ /* of the implementation and should not be of interest to clients. */ /**********************************************************************/ private: Map map; /* Map used to store the element */ bool removeFlag; /* Flag to differentiate += and -= */ public: /* * Hidden features * --------------- * The remainder of this file consists of the code required to * support the comma operator, deep copying, and iteration. * Including these methods in the public interface would make * that interface more difficult to understand for the average client. */ /* Extended constructors */ template explicit Set(CompareType cmp) : map(Map(cmp)) { /* Empty */ } Set & operator,(const ValueType & value) { if (this->removeFlag) { this->remove(value); } else { this->add(value); } return *this; } /* * Iterator support * ---------------- * The classes in the StanfordCPPLib collection implement input * iterators so that they work symmetrically with respect to the * corresponding STL classes. */ class iterator : public std::iterator { private: typename Map::iterator mapit; /* Iterator for the map */ public: iterator() { /* Empty */ } iterator(typename Map::iterator it) : mapit(it) { /* Empty */ } iterator(const iterator & it) { mapit = it.mapit; } iterator & operator=(const iterator & it) { if(*this != it){ mapit = it.mapit; } return *this; } iterator & operator++() { ++mapit; return *this; } iterator operator++(int) { iterator copy(*this); operator++(); return copy; } bool operator==(const iterator & rhs) { return mapit == rhs.mapit; } bool operator!=(const iterator & rhs) { return !(*this == rhs); } ValueType operator*() { return *mapit; } ValueType *operator->() { return mapit; } }; iterator begin() const { return iterator(map.begin()); } iterator end() const { return iterator(map.end()); } }; extern void error(std::string msg); template Set::Set() { /* Empty */ } template Set::~Set() { /* Empty */ } template int Set::size() const { return map.size(); } template bool Set::isEmpty() const { return map.isEmpty(); } template void Set::add(const ValueType & value) { map.put(value, true); } template void Set::insert(const ValueType & value) { map.put(value, true); } template void Set::remove(const ValueType & value) { map.remove(value); } template bool Set::contains(const ValueType & value) const { return map.containsKey(value); } template void Set::clear() { map.clear(); } template bool Set::isSubsetOf(const Set & set2) const { iterator it = begin(); iterator end = this->end(); while (it != end) { if (!set2.map.containsKey(*it)) return false; ++it; } return true; } /* * Implementation notes: set operators * ----------------------------------- * The implementations for the set operators use iteration to walk * over the elements in one or both sets. */ template bool Set::operator==(const Set & set2) const { if (size() != set2.map.size()) return false; iterator it1 = begin(); iterator it2 = set2.map.begin(); iterator end = this->end(); while (it1 != end) { if (map.compareKeys(*it1, *it2) != 0) return false; ++it1; ++it2; } return true; } template bool Set::operator!=(const Set & set2) const { return !(*this == set2); } template Set Set::operator+(const Set & set2) const { Set set = *this; foreach (ValueType value in set2) { set.add(value); } return set; } template Set Set::operator+(const ValueType & element) const { Set set = *this; set.add(element); return set; } template Set Set::operator*(const Set & set2) const { Set set = *this; set.clear(); foreach (ValueType value in *this) { if (set2.contains(value)) set.add(value); } return set; } template Set Set::operator-(const Set & set2) const { Set set = *this; foreach (ValueType value in set2) { set.remove(value); } return set; } template Set Set::operator-(const ValueType & element) const { Set set = *this; set.remove(element); return set; } template Set & Set::operator+=(const Set & set2) { foreach (ValueType value in set2) { this->add(value); } return *this; } template Set & Set::operator+=(const ValueType & value) { this->add(value); this->removeFlag = false; return *this; } template Set & Set::operator*=(const Set & set2) { Vector toRemove; foreach (ValueType value in *this) { if (!set2.map.containsKey(value)) toRemove.add(value); } foreach (ValueType value in toRemove) { this->remove(value); } return *this; } template Set & Set::operator-=(const Set & set2) { Vector toRemove; foreach (ValueType value in *this) { if (set2.map.containsKey(value)) toRemove.add(value); } foreach (ValueType value in toRemove) { this->remove(value); } return *this; } template Set & Set::operator-=(const ValueType & value) { this->remove(value); this->removeFlag = true; return *this; } template ValueType Set::first() const { if (isEmpty()) error("first: set is empty"); return *begin(); } template std::string Set::toString() { ostringstream os; os << *this; return os.str(); } template void Set::mapAll(void (*fn)(ValueType)) const { map.mapAll(fn); } template void Set::mapAll(void (*fn)(const ValueType &)) const { map.mapAll(fn); } template template void Set::mapAll(FunctorType fn) const { map.mapAll(fn); } template std::ostream & operator<<(std::ostream & os, const Set & set) { os << "{"; bool started = false; foreach (ValueType value in set) { if (started) os << ", "; writeGenericValue(os, value, true); started = true; } os << "}"; return os; } template std::istream & operator>>(std::istream & is, Set & set) { char ch; is >> ch; if (ch != '{') error("operator >>: Missing {"); set.clear(); is >> ch; if (ch != '}') { is.unget(); while (true) { ValueType value; readGenericValue(is, value); set += value; is >> ch; if (ch == '}') break; if (ch != ',') { error(std::string("operator >>: Unexpected character ") + ch); } } } return is; } // hashing functions for sets; defined in hashmap.cpp int hashCode(const Set& s); int hashCode(const Set& s); int hashCode(const Set& s); int hashCode(const Set& s); int hashCode(const Set& s); #endif