OrderedSet.h

00001 /*  _________________________________________________________________________
00002  *
00003  *  UTILIB: A utility library for developing portable C++ codes.
00004  *  Copyright (c) 2001, Sandia National Laboratories.
00005  *  This software is distributed under the GNU Lesser General Public License.
00006  *  For more information, see the README file in the top UTILIB directory.
00007  *  _________________________________________________________________________
00008  */
00009 
00010 //
00011 // OrderedSet.h
00012 //
00022 #ifndef __OrderedSet_h
00023 #define __OrderedSet_h
00024 
00025 #ifdef __GNUC__
00026 #pragma interface
00027 #endif
00028 
00029 #ifdef NON_ANSI
00030 #include <iostream.h>
00031 #else
00032 #include <iostream>
00033 using namespace std;
00034 #endif
00035 
00036 #ifndef ANSI_HDRS
00037 #include <stddef.h>
00038 #include <stdlib.h>
00039 #else
00040 #include <cstddef>
00041 #include <cstdlib>
00042 #endif
00043 
00044 #include "_math.h"
00045 #include "PackBuf.h"
00046 #include "BasicArray.h"
00047 
00048 
00049 typedef size_type OrderedSetIndex;
00050 
00054 
00055 template <class T>
00056 class UTILIB_API OrderedSet
00057 {
00058 public:
00059 
00061   OrderedSet();
00063   virtual ~OrderedSet() {}
00064 
00066   virtual int add( const T& val , const int unique=FALSE );
00068   virtual void add( const OrderedSet<T>&, const int unique=FALSE );
00070   virtual void remove( T& val );
00071 
00073   int empty() const
00074                 {return (Len == 0);}
00076   operator int() const
00077                 {return (Len > 0);}
00079   size_type len() const
00080                 {return Len;}
00081 
00082 
00084   T& first( OrderedSetIndex& index, int& status);
00086   T& next( OrderedSetIndex& index, int& status);
00087 
00089   int index(const T& val);
00091   int is_member(const T& val)
00092         {return (index(val) != -1);}
00094   int is_disjoint(const OrderedSet<T>& set);
00095 
00097   const T & operator[](const int i) const
00098                 {return Data[i];}
00099 
00101   void write(ostream& os) const;
00103   void read(istream& is);
00105   void write(PackBuffer& os) const;
00107   void read(UnPackBuffer& is);
00108 
00109 protected:
00110 
00112   size_type Len;
00114   BasicArray<T> Data;
00115 
00116 };
00117 
00119 template <class T>
00120 inline UTILIB_API OrderedSet<T>& operator>>(OrderedSet<T>& list, T& val)
00121 {list.remove(val); return list;}
00122 
00124 template <class T>
00125 inline UTILIB_API OrderedSet<T>& operator<<(OrderedSet<T>& list, const T& val)
00126 {list.add(val); return list;}
00127 
00129 template <class T>
00130 inline UTILIB_API ostream& operator<<(ostream& output, const OrderedSet<T>& set)
00131 { set.write(output); return(output); }
00132 
00134 template <class T>
00135 inline UTILIB_API istream& operator>>(istream& input, OrderedSet<T>& set)
00136 { set.read(input); return(input); }
00137 
00139 template <class T>
00140 inline UTILIB_API PackBuffer& operator<<(PackBuffer& output, const OrderedSet<T>& set)
00141 { set.write(output); return(output); }
00142 
00144 template <class T>
00145 inline UTILIB_API UnPackBuffer& operator>>(UnPackBuffer& input, OrderedSet<T>& set)
00146 { set.read(input); return(input); }
00147 
00148 
00149 
00150 
00151 
00152 template <class T>
00153 OrderedSet<T>::OrderedSet()
00154  : Len(0), Data(1)
00155 { }
00156 
00157 
00158 //
00159 // Note: in order to make 'removes' effective, you need to be able to deal with
00160 // 'holes' in the array.  This is messy, and I don't need this capability right
00161 // now!  -- WEH
00162 //
00163 template <class T>
00164 void OrderedSet<T>::remove( T& Value )
00165 {
00166 ErrAbort("OrderedSet<T>::remove -- unimplemented method!");
00167 }
00168 
00169 
00170 template <class T>
00171 int OrderedSet<T>::add( const T& val, const int add_unique )
00172 {
00173 int ndx = index(val);
00174 if (add_unique && (ndx != -1))
00175    return ndx;
00176 
00177 if (Data.size() == Len)
00178    Data.resize(Len + max((Data.size() / 10),(size_type)10));
00179 
00180 Data[Len] = val;
00181 Len++;
00182 return(Len-1);
00183 }
00184 
00185 
00186 
00187 template <class T>
00188 void OrderedSet<T>::add( const OrderedSet<T>& set, const int add_unique )
00189 {
00190 for (size_type i=0; i<set.Len; i++)
00191   if (!add_unique || !is_member(set.Data[i]))
00192      add(set.Data[i]);
00193 }
00194 
00195 
00196 
00197 template <class T>
00198 int OrderedSet<T>::index(const T& val)
00199 {
00200 for (size_type i=0; i<Len; i++)
00201   if (val == Data[i])
00202      return i;
00203 return -1;
00204 }
00205 
00206 
00207 template <class T>
00208 T& OrderedSet<T>::first( OrderedSetIndex& index, int& status)
00209 {
00210 if (Len == 0) {
00211    status = FALSE;
00212    return Data[0];
00213 }
00214 index = 1;
00215 status=TRUE;
00216 return Data[0];
00217 }
00218 
00219 
00220 template <class T>
00221 T& OrderedSet<T>::next( OrderedSetIndex& index, int& status)
00222 {
00223 if (status == FALSE) return Data[0];
00224 if (index >= Len) {
00225    status = FALSE;
00226    return Data[0];
00227    }
00228 return Data[index++];
00229 }
00230 
00231 template <class T>
00232 int OrderedSet<T>::is_disjoint(const OrderedSet<T>& set)
00233 {
00234 for (size_type i=0; i<Len; i++)
00235   for (size_type j=0; j<set.Len; j++)
00236     if (Data[i] == set.Data[j]) return FALSE;
00237 return TRUE;
00238 }
00239 
00240 
00241 template <class T>
00242 void OrderedSet<T>::write(ostream& os) const
00243 {
00244 os << "{ ";
00245 if (Len > 0) {
00246    os << Data[0];
00247    for (size_type i=1; i<Len; i++)
00248      os << ", " << Data[i];
00249    os << " ";
00250    }
00251 os << "}";
00252 }
00253 
00254 
00255 template <class T>
00256 void OrderedSet<T>::read(istream& /*is*/)
00257 {
00258 }
00259 
00260 
00261 template <class T>
00262 void OrderedSet<T>::write(PackBuffer& os) const
00263 {
00264 os << Len;
00265 for (size_type i=0; i<Len; i++)
00266   os << Data[i];
00267 }
00268 
00269 
00270 template <class T>
00271 void OrderedSet<T>::read(UnPackBuffer& is)
00272 {
00273 is >> Len;
00274 if (Data.len() <= Len)
00275    Data.resize(max(1,Len));
00276 for (size_type i=0; i<Len; i++)
00277   is >> Data[i];
00278 }
00279 
00283 #define ForAllElements(index,set,elt_type)\
00284 if (set.len() > 0) {\
00285 int index ## __first=TRUE, index ## __status=TRUE;\
00286 OrderedSetIndex index ## __ndx;\
00287 while (index ## __status == TRUE) {\
00288   const elt_type& index = (index ## __first == TRUE ? set.first(index ## __ndx, index ## __status) : set.next(index ## __ndx, index ## __status));\
00289   index ## __first = FALSE;\
00290   if (index ## __status == FALSE) break;
00291 
00292 
00293 #endif