/**** * * Class List is a generic list type. An object of type List* points to a * structure containing zero or more list elements of type ListElem*. A * ListElem has the following abstract structure: * * |-------------------------------| * | orderable key | * |-------------------------------| * | optional specialized data | * | ... | * |-------------------------------| * * An object of type ListElem* contains no key or data itself. Rather, List, * ListElem, and ListElemKey are intended to be specialized to define specific * kinds of lists, in which elements have specialized types of keys and data. * For examples of typical list specializations, see the files intlist.{h,C} * and strlist.{h,C} which define lists of ints and strings, respectively. * * Regarding performance, lists on the order of 10,000 elements or less behave * reasonably well, on a machine with power in the realm of an HP700. E.g., * constructing or searching a 10,000-element list of strings takes less than a * second. Performance degradation starts with lists of around 100,000 * elements or more, where constructing takes 10 or 15 seconds. Hence, * collections on the order of 100,000 elements or greater should use a more * efficient representation than this list provides. Future implementations of * this list class may improve performance, but the reader ought not hold * her/his breath. * */ #ifndef listIncluded #define listIncluded #include "std-macros.h" class ListElem; class ListElemKey; class ListItem; class List { public: List(); /* * Construct a new empty list. Set the internal enumerator state to null. * * post: (first == null) and (last == null) and (size == 0) and * (curpos == 0) and (gotitem == null) and (enumstate == null) */ ~List(); /* * Deep delete this, i.e., call delete on each element. * * post: forall (e:ListElem | this'->Find(e->GetKey()) != null) * freed(e); */ List* Put(ListElem* e); /* * Put the given element onto the end of this (fifo discipline). Return * the changed value of this. Reset the internal enumerator state of this * to the first element. * * post: */ ListElem* Pull(); /* * Remove and return the last element off the end of this (i.e., the last * element put by Put). Return null if this is empty. Reset the internal * enumerator state of this to the first element, if this is not empty, to * null otherwise. */ List* Push(ListElem* e); /* * Push the given element onto the front of this (lifo discipline). Return * the changed value of this. Reset the internal enumerator state of this * to the first element. */ ListElem* Pop(); /* * Remove and return the first element from the front of this (i.e., the * last element pushed by Push). Return null if this is null. Reset the * internal enumerator state of this to the first element, if this is not * empty, to null otherwise. */ List* Insert(ListElem* e, int n); /* * Insert the given element after the given position n, for 1 <= n <= * this->Len(). Insert before the first element if n = 0. Do nothing if n * < 0 or n > this->Len(). Return the changed or unchanged value of this. * Reset the internal enumerator state of this to the n+1st element if 0 <= * n < this->Len(); reset the enuerator state to the first element if n = * this->Len(); leave the enumerator state unchnged otherwise. */ ListElem* GetNth(int n); /* * Return the nth element of this without removing it, for 1 <= n <= * this->Len(). Return null if n < 1 or n > this->Len(). Reset the * internal enumerator state of this to the nth element if 1 <= n <= * this->Len(); leave the enumerator state unchanged otherwise. */ ListElem* RemoveNth(int n); /* * Remove and return the nth element from this, for 1 <= n <= this->Len(); * do nothing and return null if n<1 or n>this->Len(). Reset the internal * enumerator state to the (new) nth element if 1 <= n < this->Len() and * this is not empty; reset the enuerator state to the first element if n = * this->Len() and this is not empty; reset the enumerator state to null if * this is empty; leave the enumerator state unchanged otherwise. */ ListElem* DelNth(int n) {return RemoveNth(n);} /* * Old name for RemoveNth (for backward compatibility). */ ListElem* Find(ListElemKey* k); /* * Return the first element e of this such that e->Compare(k) is true. * Return null if no such element is found. Reset the internal enumerator * state of this to the position of the found element if an element was * found; leave the enumerator state unchanged otherwise. */ int FindPos(ListElemKey* k); /* * Return the position in this of the first element e such that * e->Compare(k) is true. Return 0 if no such element is found. Reset the * internal enumerator state of this to the element at the returned * position if non-zero; leave the enumerator state unchanged otherwise. */ int Len(); /* * Return the number of elements in this. */ ListElem* Enum(); /* * Enumerate all elements of this, starting from the element specified by * the current enumerator state, as set by one of the functions described * above. Successive calls to Enum will return the next successive * element, as long as no intervening call is made to a function that * resets the enumerator state. Null is returned if this is empty or at * the end of the enumeration of a non-empty list. */ void ResetEnum(); /* * Reset the internal enumerator state of this to the first element if this * is not empty, to null otherwise. */ List* Sort(bool ascending = true); /* * Sort this, based on the key ordering defined by the virtual function * ListElem::Compare(ListElemKey*). If ascending = true, sort in ascending * key order, else in descending order. Return the sorted value of this. */ void Print(); /* * Print each list element e of this using the virtual function e->Print(). */ protected: ListItem* first; /* Pointer to head elem. */ ListItem* last; /* Pointer to tail elem */ int size; /* Current size for efficiency */ int curpos; /* Position of elem found by last Find or * FindPos */ ListItem* gotitem; /* Last item found by GetNth */ ListItem* enumstate; /* Next item to return from Enum */ }; class ListElem { public: ListElem(); /* * Construct a new empty list element. */ virtual ~ListElem(); /* * Delete a list elememnt. */ virtual int Compare(ListElem* e); /* * Compare this with the given list element, returning an int per the * conventions of C strcmp. Viz., return -1 if this < k; 0 if this = key; * 1 if this > e. Compare has a noop default implementation, in particular * it uncondtionally returns 0. Compare must be specialized to produce * meaningful output. */ virtual int Compare(ListElemKey* k); /* * Compare this->GetKey() with the given list element key, returning an int * per the conventions of C strcmp. Viz., return -1 if this < k; 0 if this * = key; 1 if this > e. Compare has a noop default implementation, in * particular it uncondtionally returns 0. Compare must be specialized to * produce meaningful output. */ virtual ListElemKey* GetKey(); /* * Return the key value of this, null if no key exists. Key has a noop * default implementation, in particular it unconditionally returns null. * GetKey it must be specialized to produce meaningful output. */ virtual void Print(); /* * Print this to stdout. Print has a noop default implementation -- it * must be specialized to perform any useful work. */ }; /**** * * Class ListElemKey is a completely opaque type, used as a place holder for * the key type in functions List::Find and ListElem::Compare. * */ class ListElemKey {}; /**** * * Class ListItem is the type of the protected represention of class List. An * object of type ListItem holds the internal representation of items in the * linked list implementation. * */ class ListItem { friend class List; protected: ListItem(); /* * Construct an unintialized item. */ ~ListItem(); /* * Shallow delete this, i.e., do NOT delete this->data. */ void Swap(ListItem* i); /* * Swap the data element of this with the data element of the given item. */ ListElem* data; /* Pointer to the visible list elem data */ ListItem* next; /* Hidden next link */ ListItem* prev; /* Hidden prev link */ }; #endif