//====================================================================== // File: list.h // Author: Timothy A. Budd // Description: This file contains the interface of the list // classes. // // Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. //====================================================================== #ifndef LIST_H #define LIST_H #include #include "iterator.h" //---------------------------------------------------------------------- // class list // arbitrary size lists of elements // permits insertion and removal only // from the front of the list //---------------------------------------------------------------------- template class link; template class listIterator; template class list { public: // constructors list(); list(const list & source); virtual ~list(); // operations void add(T value); virtual void deleteAllValues(); list * duplicate(); T firstElement() const; virtual int includes(T value) const; int isEmpty() const; virtual void removeFirst(); //protected: g++ change public: // data field link * ptrToFirstLink; // friends friend class listIterator; }; //---------------------------------------------------------------------- // class link // facilitator for operations on lists // maintains a single element for the linked list class //---------------------------------------------------------------------- template class link { public: // insert a new element following the current value link * insert(T val); // private: g++ change public: // constructor link(T linkValue, link * nextPtr); // duplicate link * duplicate(); // data areas T value; link * ptrToNextLink; // friends friend class list; friend class listIterator; }; //---------------------------------------------------------------------- // class listIterator // implements iterator protocol for linked lists // also permits removal and addition of elements //---------------------------------------------------------------------- template class listIterator : public iterator { public: // constructor listIterator(list & aList); // iterator protocol virtual int init(); virtual T operator ()(); virtual int operator !(); virtual int operator ++(); virtual void operator =(T value); // new methods specific to list iterators void removeCurrent(); void addBefore(T newValue); void addAfter(T newValue); // protected: g++ change public: // data areas link * currentLink; link * previousLink; list & theList; }; //---------------------------------------------------------------------- // class orderedList // a list structure where each element // is maintained in sequence based on the // less-than comparison operator //---------------------------------------------------------------------- template class orderedList : public list { public: // change the addition method void add(T value); }; //---------------------------------------------------------------------- // class list implementation //---------------------------------------------------------------------- template list::list() : ptrToFirstLink(0) { // no further initialization } template list::list(const list & source) { // duplicate elements from source list if (source.isEmpty()) ptrToFirstLink = 0; else { link * firstLink = source.ptrToFirstLink; ptrToFirstLink = firstLink->duplicate(); } } template list::~list() { // empty all elements from the list deleteAllValues(); } template void list::add(T val) { // add a new value to the front of a linked list ptrToFirstLink = new link(val, ptrToFirstLink); assert(ptrToFirstLink != 0); } template void list::deleteAllValues() { // clear all items from the list link * next; for (link * p = ptrToFirstLink; p != 0; p = next) { // delete the element pointed to by p next = p->ptrToNextLink; p->ptrToNextLink = 0; delete p; } // mark that the list contains no elements ptrToFirstLink = 0; } template list * list::duplicate() { list * newlist = new list; assert(newlist != 0); // copy list if (ptrToFirstLink) newlist->ptrToFirstLink = ptrToFirstLink->duplicate(); // return the new list return newlist; } template T list::firstElement() const { // return first value in list assert(ptrToFirstLink != 0); return ptrToFirstLink->value; } template int list::includes(T v) const { // loop to test each element for (link * p = ptrToFirstLink; p; p = p->ptrToNextLink) if (v == p->value) return 1; // not found return 0; } template int list::isEmpty() const { // test to see if the list is empty // list is empty if the pointer to the first link is null return ptrToFirstLink == 0; } template void list::removeFirst() { // make sure there is a first element assert(ptrToFirstLink != 0); // save pointer to the removed node link * p = ptrToFirstLink; // reassign the ptrToFirstLink node ptrToFirstLink = p->ptrToNextLink; // recover memory used by the first element delete p; } //---------------------------------------------------------------------- // class link implementation //---------------------------------------------------------------------- template link * link::insert(T val) { // insert a new link after current node ptrToNextLink = new link(val, ptrToNextLink); // check that allocation was successful assert(ptrToNextLink != 0); return ptrToNextLink; } template link::link(T val, link * nxt) : value(val), ptrToNextLink(nxt) { // create and initialize a new link field } template link * link::duplicate() { link * newlink; // if there is a next field. copy remainder of list if (ptrToNextLink != 0) newlink = new link(value, ptrToNextLink->duplicate()); else newlink = new link(value, 0); // check that allocation was successful assert(newlink != 0); return newlink; } //---------------------------------------------------------------------- // class listIterator implementation //---------------------------------------------------------------------- template listIterator::listIterator(list & aList) : theList(aList) { // create and initialize a new list init(); } template int listIterator::init() { // set the iterator to the first element in the list previousLink = 0; currentLink = theList.ptrToFirstLink; return currentLink != 0; } template T listIterator::operator ()() { // return value of current element // check to see if there is a current element assert(currentLink != 0); // return value associated with current element return currentLink->value; } template int listIterator::operator !() { // test for termination of the iterator // if current link references a removed value, // update current to point to next position if (currentLink == 0) if (previousLink != 0) currentLink = previousLink->ptrToNextLink; // now see if currentLink is valid return currentLink != 0; } template int listIterator::operator ++() { // move current pointer to nect element // special processing if current link is deleted if (currentLink == 0) { if (previousLink == 0) currentLink = theList.ptrToFirstLink; else currentLink = previousLink->ptrToNextLink; } else { // advance pointer previousLink = currentLink; currentLink = currentLink->ptrToNextLink; } // return true if we have a valid current element return currentLink != 0; } template void listIterator::operator =(T val) { // modify value of current element assert(currentLink != 0); // modify value of the current link currentLink->value = val; } template void listIterator::removeCurrent() { // remove the current element from a list // make sure there is a current element assert(currentLink != 0); // case 1, removing first element if (previousLink == 0) theList.ptrToFirstLink = currentLink->ptrToNextLink; // case 2, not removing the first element else previousLink->ptrToNextLink = currentLink->ptrToNextLink; // delete current node delete currentLink; // and set current pointer to null currentLink = 0; } template void listIterator::addBefore(T val) { // a a new element to list before current value // case 1, not at start if (previousLink) previousLink = previousLink->insert(val); // case 2, at start of list else { //theList.list::add(val); // g++ change theList.add(val); previousLink = theList.ptrToFirstLink; currentLink = previousLink->ptrToNextLink; } } template void listIterator::addAfter(T val) { // a a new element to list after current value // case 1, not at start if (currentLink != 0) currentLink->insert(val); // case 2, at end of list else if (previousLink != 0) currentLink = previousLink->insert(val); // case 3, start of list else //theList.list::add(val); // g++ change theList.add(val); } //---------------------------------------------------------------------- // class orderedList implementation //---------------------------------------------------------------------- template void orderedList::add(T val) { // add a new value to an ordered list // loop over values smaller than current listIterator itr(*this); for (itr.init(); !itr; itr++) if (val < itr()) { // found location to insert value itr.addBefore(val); return; } // add to end of list if not yet inserted itr.addBefore(val); } #endif