//====================================================================== // File: set.h // Author: Timothy A. Budd // Description: This file contains the interface and implementation // of the set and bag template classes. // // Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. //====================================================================== #ifndef SET_H #define SET_H #include "iterator.h" #include "vector.h" #include "list.h" #include "hash.h" //---------------------------------------------------------------------- // class setList // set protocol built on top of list implementation //---------------------------------------------------------------------- template class setList : public list { public: // add an item to the set virtual void add(T val); // removal test virtual void remove(T); // union formation void unionWith(setList &); // intersection void intersectWith(setList &); // difference between sets void differenceFrom(setList &); // subset test int subset(setList &); }; //---------------------------------------------------------------------- // class setTable // set protocol built out of hash tables //---------------------------------------------------------------------- template class setTable : public hashTable, T, T> { public: // constructor setTable(unsigned int max, unsigned int (*f)(const T &)); // implement set protocol void add(T val); void differenceFrom(setTable &); int includes(T val) const; void intersectWith(setTable &); void remove(T val); void unionWith(setTable &); int subset(setTable &) const; protected: // make an iterator iterator * makeIterator(unsigned int i); }; //---------------------------------------------------------------------- // set template functions (for class iterator) //---------------------------------------------------------------------- template void setUnionWith(ST & set, iterator & itr) { // simply add every element from the argument iterator for (itr.init(); ! itr; itr++) set.add(itr()); } template void setDifferenceFrom(ST & set, iterator & itr) { // test every element to see if it is in the receiver for (itr.init(); ! itr; itr++) // if current set has it if (set.includes(itr())) // then remove it set.remove(itr()); } template int setSubset(ST & set, iterator & itr) { // every element of right must also be in receiver for (itr.init(); ! itr; itr++) // if set does not have it if (! set.includes(itr())) // then can't be a subset return 0; // everything checks out, must be a subset return 1; } template void setIntersectWith(ST & set, iterator & itr) { // make a list of elements in the difference list difference; // for each element in iterator for (itr.init(); ! itr; itr++) // if it is not in set if (! set.includes(itr())) // then save it difference.add(itr()); // now remove elements from the difference listIterator litr(difference); for (litr.init(); ! litr; litr++) set.remove(litr()); } //---------------------------------------------------------------------- // set template functions (for class listIterator) //---------------------------------------------------------------------- template void setUnionWith(ST & set, listIterator & itr) { // simply add every element from the argument iterator for (itr.init(); ! itr; itr++) set.add(itr()); } template void setDifferenceFrom(ST & set, listIterator & itr) { // test every element to see if it is in the receiver for (itr.init(); ! itr; itr++) // if current set has it if (set.includes(itr())) // then remove it set.remove(itr()); } template int setSubset(ST & set, listIterator & itr) { // every element of right must also be in receiver for (itr.init(); ! itr; itr++) // if set does not have it if (! set.includes(itr())) // then can't be a subset return 0; // everything checks out, must be a subset return 1; } template void setIntersectWith(ST & set, listIterator & itr) { // make a list of elements in the difference list difference; // for each element in iterator for (itr.init(); ! itr; itr++) // if it is not in set if (! set.includes(itr())) // then save it difference.add(itr()); // now remove elements from the difference listIterator litr(difference); for (litr.init(); ! litr; litr++) set.remove(litr()); } //---------------------------------------------------------------------- // class setList implementation //---------------------------------------------------------------------- template void setList::add(T val) { // only add if it is not already in the set if (! includes(val)) list::add(val); } template void setList::remove(T val) { listIterator itr(*this); for (itr.init(); ! itr; itr++) if (itr() == val) { itr.removeCurrent(); return; } } template void setList::unionWith(setList & right) { // simply make an iterator and then use the generic method listIterator itr(right); setUnionWith(*this, itr); } template void setList::intersectWith(setList & right) { // simply make an iterator and then use the generic method listIterator itr(right); setIntersectWith(*this, itr); } template void setList::differenceFrom(setList & right) { // simply make an iterator and then use the generic method listIterator itr(right); setDifferenceFrom(*this, itr); } template int setList::subset(setList & right) { // simply make an iterator and then use the generic method listIterator itr(right); return setSubset(*this, itr); } template int operator == (setList & left, setList & right) { // two sets are equal if both are subsets of each other return left.subset(right) && right.subset(left); } //---------------------------------------------------------------------- // class setTable implementation //---------------------------------------------------------------------- template setTable:: setTable(unsigned int max, unsigned int (*f)(const T &)) : hashTable, T, T>(max, f) { // no further initialization } template void setTable::add(T val) { // compute bucket, then add element buckets[hash(val)].add(val); } template void setTable::differenceFrom(setTable & right) { assert(tablesize == right.tablesize); // form the difference of each bucket independently for (int i = 0; i < tablesize; i++) buckets[i].differenceFrom(right.buckets[i]); } template int setTable::includes(T val) const { // compute bucket, then see if it includes element return buckets[hash(val)].includes(val); } template void setTable::intersectWith(setTable & right) { assert(tablesize == right.tablesize); // form the intersection of each bucket independently for (int i = 0; i < tablesize; i++) buckets[i].intersectWith(right.buckets[i]); } template void setTable::remove(T val) { // compute bucket, then remove element buckets[hash(val)].remove(val); } template void setTable::unionWith(setTable & right) { assert(tablesize == right.tablesize); // form the union of each bucket independently for (int i = 0; i < tablesize; i++) buckets[i].unionWith(right.buckets[i]); } template int setTable::subset(setTable & right) const { assert(tablesize == right.tablesize); // test subset of each bucket independently for (int i = 0; i < tablesize; i++) if (! buckets[i].subset(right.buckets[i])) return 0; // all bucket subsets smaller than corresponding buckets return 1; } template iterator * setTable:: makeIterator(unsigned int i) { return new listIterator(buckets[i]); } #endif