#ifndef FLEX_SET_H #define FLEX_SET_H #include "flexarrays.h" /* * A flexset is a set datastructure. Fast insertion/deletion (O(logN)), * and basic set operations (union, difference, etc...). This set is * not completely generalized - you must either use native (non-pointer) * types, or use a class with operators < and == implemented * (i.e: inline int operator<(const X&) const{...};) This is what allows * log time access, and linear time set operations. * Routines: * Constructor/Destructor/copy constructor... * * Information: * int getSize() - returns size of set. * int find(X& x) - return position of x, or -1 if x isn't in the set * int contains(X& x) - boolean version of above * int contains(flexset &s) - returns 1 if s is a subset * * Manipulation: * insert(X& x) - add x to the set. If x is already in the set * (technically, x==e for some e in the set) nothing happens. * remove(X& x) - remove x (only if x is inside, of course); * X& [int idx] - access element by index. Index will change with insertion * buldSubset(flexset &x, int (* test)(X& y)) - creates a subset consisting * of all elements in the set for which 'test' returns true. * * Operations: * [all of form: set(X& A, X& B, X& result){ result= A B}] * setunion(A=AUB, or C=AUB), setintersection, setdifference, setsymmetricdifference * setdifferences (returns A-B and B-A in one go) * NOTE: The result of intersection or difference will consist only * of items taken from A. (Important if you are comparing sets with * similar keys and dissimilar data */ /* class flexset; template setiter{ public: setiter(flexset *nset){itsset=nset; idx=(nset->empty())?-1:0;} operator++(){idx++; if (idx>itsset->getSize()-1) idx=-1;} operator--(){idx--; if (idx<0) idx=-1;} int ok(){return idx!=-1;} X &operator*(){if (idx==-1) return itsset[0]; return itsset[idx];} private: flexset *itsset; int idx; } */ template class flexset : protected flexarray{ public: flexset(): flexarray(){}; flexset(const flexset &src): flexarray(src){}; ~flexset(){}; //by all accounts, this should inherit flexarray operator= int getSize() const{return flexarray::getSize();} int findpos(const X &elt, int start=0, int end=-1) const{ if (start<0) start=0; if (end==-1) end=getLength()-1; int a=start, b=end, e; if (empty()) return 0; if (elt<(*this)(a)) return a; if (elt==(*this)(a)) return a; //don't depend on <= being implemented if (elt==(*this)(b)) return b; if (!(elt<(*this)(b))) return b+1; //given above line, equiv to elt>data[b] if ((a+b)&1) e=(a+b+1)/2; //e odd else e=(a+b)/2; while ((b-a>1)){ if (elt==(*this)(e)) return e; if (elt<(*this)(e)) b=e; else a=e; if ((a+b)&1) e=(a+b+1)/2; //e odd else e=(a+b)/2; } if (elt<(*this)(e)) return e; if (elt==(*this)(e)) return e; else return e+1; } //If elt is in the set, return its index, otherwise return -1 int find(const X &elt, int start=0, int end=-1) const{ if (empty()) return -1; int result=findpos(elt, start, end); if (result &iset) const{ if (iset.empty()) return 1; //Empty set is in everything! int a=find(iset(0)); if (a<0)return 0; for (int ii=1;ii::clear(); } int empty() const {return flexarray::empty();} void buildSubset(flexset &A, int (* test)(const X&)){ A.clear(); for (int ii=0;ii=getSize()) return; removeElements(idx, 1); } void append(const X &elt){ if (empty()) { insertElement(elt, 0); return; } X *tmp=&(*this)[getSize()-1]; if ((*tmp) &A, const flexset &B,flexset &result); friend void setintersection(const flexset &A, const flexset &B,flexset &result); friend void setsymmetricdifference(const flexset &A, const flexset &B,flexset &result); friend void setdifference(const flexset &A, const flexset &B,flexset &result); friend void setdifferences(const flexset &A, const flexset &B,flexset &AMB,flexset &BMA); friend void setconvert(flexset &A, const flexset &B); }; template void setunion(const flexset &A, const flexset &B,flexset &result); template void setunion(flexset &A, const flexset &B); template void setintersection(const flexset &A, const flexset &B,flexset &result); template void setsymmetricdifference(const flexset &A, const flexset &B,flexset &result); template void setdifference(const flexset &A, const flexset &B,flexset &result); template void setdifferences(const flexset &A, const flexset &B,flexset &AMB,flexset &BMA); template void setconvert(flexset &A, const flexset &B); #endif