set;
* ------------------------------
* Initializes an empty set of the specified element type.
*/
HashSet();
/*
* Destructor: ~HashSet
* --------------------
* Frees any heap storage associated with this set.
*/
virtual ~HashSet();
/*
* 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 HashSet & 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 HashSet & set2) const;
/*
* Operator: !=
* Usage: set1 != set2
* -------------------
* Returns true if set1 and set2
* are different.
*/
bool operator!=(const HashSet & 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.
*/
HashSet operator+(const HashSet & set2) const;
HashSet 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.
*/
HashSet operator*(const HashSet & 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.
*/
HashSet operator-(const HashSet & set2) const;
HashSet 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
* HashSet package also overloads the comma operator so
* that it is possible to initialize a set like this:
*
*
* HashSet<int< digits;
* digits += 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
*
*/
HashSet & operator+=(const HashSet & set2);
HashSet & operator+=(const ValueType & value);
/*
* Operator: *=
* Usage: set1 *= set2;
* --------------------
* Removes any elements from set1 that are not present in
* set2.
*/
HashSet & operator*=(const HashSet & set2);
/*
* Operator: -=
* Usage: set1 -= set2;
* set1 -= value;
* ---------------------
* Removes the elements from set2 (or the single
* specified value) from set1. As a convenience, the
* HashSet 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.
*/
HashSet & operator-=(const HashSet & set2);
HashSet & 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 HashSet operations
* -----------------------------
* In addition to the methods listed in this interface, the HashSet
* 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 HashSet in an unspecified 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:
HashMap 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.
*/
HashSet & 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 HashMap::iterator mapit;
public:
iterator() {
/* Empty */
}
iterator(typename HashMap::iterator it) : mapit(it) {
/* Empty */
}
iterator(const iterator & it) {
mapit = it.mapit;
}
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
HashSet::HashSet() {
/* Empty */
}
template
HashSet::~HashSet() {
/* Empty */
}
template
int HashSet::size() const {
return map.size();
}
template
bool HashSet::isEmpty() const {
return map.isEmpty();
}
template
void HashSet::add(const ValueType & value) {
map.put(value, true);
}
template
void HashSet::insert(const ValueType & value) {
map.put(value, true);
}
template
void HashSet::remove(const ValueType & value) {
map.remove(value);
}
template
bool HashSet::contains(const ValueType & value) const {
return map.containsKey(value);
}
template
void HashSet::clear() {
map.clear();
}
template
bool HashSet::isSubsetOf(const HashSet & 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 HashSet::operator==(const HashSet & set2) const {
return this->isSubsetOf(set2) && set2.isSubsetOf(*this);
}
template
bool HashSet::operator!=(const HashSet & set2) const {
return !(*this == set2);
}
template
HashSet HashSet::operator+(const HashSet & set2) const {
HashSet set = *this;
foreach (ValueType value in set2) {
set.add(value);
}
return set;
}
template
HashSet
HashSet::operator+(const ValueType & element) const {
HashSet set = *this;
set.add(element);
return set;
}
template
HashSet HashSet::operator*(const HashSet & set2) const {
HashSet set;
foreach (ValueType value in *this) {
if (set2.map.containsKey(value)) set.add(value);
}
return set;
}
template
HashSet HashSet::operator-(const HashSet & set2) const {
HashSet set;
foreach (ValueType value in *this) {
if (!set2.map.containsKey(value)) set.add(value);
}
return set;
}
template
HashSet
HashSet::operator-(const ValueType & element) const {
HashSet set = *this;
set.remove(element);
return set;
}
template
HashSet & HashSet::operator+=(const HashSet & set2) {
foreach (ValueType value in set2) {
this->add(value);
}
return *this;
}
template
HashSet & HashSet::operator+=(const ValueType & value) {
this->add(value);
this->removeFlag = false;
return *this;
}
template
HashSet & HashSet::operator*=(const HashSet & 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
HashSet & HashSet::operator-=(const HashSet & 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
HashSet & HashSet::operator-=(const ValueType & value) {
this->remove(value);
this->removeFlag = true;
return *this;
}
template
ValueType HashSet::first() const {
if (isEmpty()) error("first: set is empty");
return *begin();
}
template
std::string HashSet::toString() {
ostringstream os;
os << *this;
return os.str();
}
template
void HashSet::mapAll(void (*fn)(ValueType)) const {
map.mapAll(fn);
}
template
void HashSet::mapAll(void (*fn)(const ValueType &)) const {
map.mapAll(fn);
}
template
template
void HashSet::mapAll(FunctorType fn) const {
map.mapAll(fn);
}
template
std::ostream & operator<<(std::ostream & os, const HashSet & 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, HashSet & 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 hash sets; defined in hashmap.cpp
int hashCode(const HashSet& s);
int hashCode(const HashSet& s);
int hashCode(const HashSet& s);
int hashCode(const HashSet& s);
int hashCode(const HashSet& s);
#endif