#ifndef RCITLIST_H #define RCITLIST_H #ifndef __IOSTREAM_H #include #endif #ifndef __FSTREAM_H #include #endif #include // This file contains templates for a simple linked list, the link // and a list iterator // The list in this file has a counted pointer that holds a pointer // to the first item in the list. As in all counted pointer implementations // the assigment operator and memberwise copy constructor build aliases // for the list. This saves memory and allows the user to easily see if // there are memory leaks. The fact that all standard copying functions // create aliases means that if you want a copy that will change without // affecting the original you must use the function List::copy to create // a copy that is not an alias. template class ListIterator; template class Link { public: Link(const Type &LinkValue,Link *nextPtr);//creates a new node with specified value and next item Link() {ptrToNextLink = NULL;} virtual Link* insert(const Type &val); //insert item following this Link Link* duplicate();// recursively duplicates list starting at this node virtual Link* getNext(){return ptrToNextLink;}// returns pointer to next node virtual Link* removeNext();// removes next node and adjusts next to next->next Type& value(){return _value;} // returns a reference to data in node virtual ostream& print(ostream &s){return s<<_value;} virtual istream& read(istream &s){return s>>_value;} protected: Type _value; // data stored in node Link *ptrToNextLink;// link to next item }; template class List { public: List(){ptrToFirstItem = new RCPtr;_size = 0;} List(const List&); virtual ~List(); virtual void add(const Type &value); // add to head of List void append(const Type &value); // add this value to end of the list int insert(const Type &value); // insert value if it is not in the list // in the simple list this is insert at end int insertAt(int where,const Type &value);// inserts at location where if possible (returns 1) otherwise returns 0 void deleteAllValues(); // delete all items in List inline Type firstElement(); // returns first int virtual int locate(const Type &value)const; // is value in the List virtual int locateNext(int after,const Type &value)const;// used to find next occurence of a value void removeFirst(); // delete the first item in the list void removeValue(const Type&); // remove the given item from the list inline int isEmpty()const; // is the list empty inline int size()const {return _size;} // how large is the list List copy(); // creates a copy of the list not an alias int fwrite(const char* fName); // prints file fName, returns 1 if ok 0 otherwise ostream& fwrite(ostream&); // print the list to the given ostream int fread(const char* fName); // opens the file fName returns 1 if file read 0 otherwise virtual istream& fread(istream&);// reads from a file beginning with number of items in list void terminalPrint(); // print the list to the screen virtual ListIterator* genIterator();// generates an iterator for a type of list protected: class RCPtr // This is the counted pointer type used to store the first link { public: RCPtr(){data = NULL;count = 1;} RCPtr(Link *p){data = p;count = 1;} ~RCPtr(){} Link *data; // actual pointer to first node in list int count; // how many copies of list are active }; RCPtr *ptrToFirstItem; // pointer to node containing head of the List int _size; // size of the list friend class ListIterator; }; template class ShallowList :public List { public: ShallowList(Link*,int);// builds a part of a list starting at the link virtual ~ShallowList() // kills the connect to the list so original list left intact { ptrToFirstItem->data = NULL;//ptrToFirstItem is deleted in ~List->deleteAllItems }//list left intact }; template class ListIterator { public: ListIterator(List &list); //~ListIterator(){cout<<"ListIterator destroyed\n";}//used to trace debugs virtual int init(); Type& operator()(); // return current value Type operator()(int place){return moveTo(place);} //move to this location in the list return the value int operator ! (); //end of list int operator ++(); //next item in list prefix operator int operator ++(int); //postfix get next item in list void operator = (const Type &value); //set the current to value virtual void removeCurrent(); // remove node at current location virtual void addBefore(const Type &newValue); // add before current location virtual void addAfter (const Type &newValue); // add after current location // the two locate functions return the location of the item if found 0 otherwise virtual int locate(const Type&); // locate the first occurrence of an item virtual int locateNextAfter(int,const Type&); // locate first occurrence of item after integer position Type& operator [](int place) {return moveTo(place);} // return a reference to data at current location ListIterator spawn();//test list cloning creates an iterator for part of the list int position(){return _pos;} operator int (); //used in while loop to determine the end of a list protected: virtual Type& moveTo(int); // move to this location in the list return value virtual void moveToNext(); //advances one through list Link *current; Link *previous; List &theList; //reference to list int _pos; //used to keep the current position in list }; template class OrderedIterator :public ListIterator { public: OrderedIterator(List &l):ListIterator(l){} virtual int locate(const Type&); }; template class OrderedList : public List { public: OrderedList():List(){} OrderedList(const OrderedList &l):List(l){} virtual ListIterator* genIterator(); int readAndOrder(const char* fName);// opens the file fName returns 1 if file read 0 otherwise istream& readAndOrder(istream&); // reads from an unordered file //and creates an ordered list friend class OrderedIterator; }; //************ code for classes **************************************** // ** code for Link ******** //****** non-member io operators for link* *********** template ostream& operator <<(ostream &s,Link *l) { return l->print(s);//*** print is virtual so may be adjusted as needed } template istream& operator >>(istream &s, Link*l) { return l->read(s);//*** read is virtual so may be adjusted as needed } template ostream& operator <<(ostream &s,Link l) { return l.print(s);//*** print is virtual so may be adjusted as needed } template istream& operator >>(istream &s, Linkl) { return l.read(s);//*** read is virtual so may be adjusted as needed } //*** end of io non-member operators template Link::Link(const Type &val, Link *nxt) :_value(val),ptrToNextLink(nxt){} template Link* Link::insert(const Type &val) { ptrToNextLink = new Link (val, ptrToNextLink); assert(ptrToNextLink != NULL); return ptrToNextLink; } template Link* Link::removeNext() { Link* temp = ptrToNextLink; if (temp) { ptrToNextLink = temp->ptrToNextLink; delete temp; } return this; } template Link* Link::duplicate() { Link *newLink; if(ptrToNextLink != NULL) newLink = new Link(_value, ptrToNextLink->duplicate());//recursive step else newLink = new Link(_value,NULL); assert(newLink != NULL); return newLink; } //***************** code for list *************** template void List::add(const Type &val) { Link *p = new Link(val,ptrToFirstItem->data); assert(p!=NULL); ptrToFirstItem->data = p; _size++; } template void List::append(const Type &value) { ListIteratorloc(*this); loc.init(); for(int i = 1;i<=_size;i++) loc++; loc.addAfter(value); } template int List::insert(const Type &value) { ListIterator* next = genIterator(); if(!next->locate(value)) { next->addBefore(value); delete next; return 1; } delete next; return 0; } template int List::insertAt(int where,const Type &value) { if(where<1 || where>_size +1) return 0; ListIteratorloc(*this); loc.init(); for(int i = 1;i void List::removeFirst() { Link *p = ptrToFirstItem->data; if (p != NULL) { ptrToFirstItem->data = p->getNext(); delete p; _size--; } } template List::~List() { // cout<<"List destructor\n"; if(--(ptrToFirstItem->count)==0) { deleteAllValues(); delete ptrToFirstItem; } } template void List::deleteAllValues() { Link *next; for (Link *p = ptrToFirstItem->data; p !=NULL; p = next) { next = p->getNext(); delete p; } _size = 0; } template List::List(const List &source) { _size = source._size; ptrToFirstItem = source.ptrToFirstItem; ptrToFirstItem->count++; } template List List::copy() { List L; L._size = _size; Link *firstLink = ptrToFirstItem->data; L.ptrToFirstItem->data = firstLink->duplicate(); return L; } template int List::locate(const Type &v)const { return locateNext(0,v); } template int List::locateNext(int after,const Type &v) const { ListIterator next(*this); int loc = after + 1; for(next(loc);!next;next++) if(next()==v) return next.position(); return 0; } template inline int List::isEmpty()const { return _size == 0; } template inline Type List::firstElement() { Type badReturn; if (ptrToFirstItem->data) return ptrToFirstItem->data->value(); else return badReturn; } template void List::terminalPrint() { ListIterator next(*this); while (!next) { cout< int List::fwrite(const char* fName) { ofstream out(fName,ios::out);// ios::out is default-so not needed if (!out)//then failed to open the file { cerr <<"Unable to open this file "< ostream& List::fwrite(ostream &s) { ListIterator next(*this); s << _size< int List::fread(const char* fName) { ifstream in (fName,ios::in); if (!in) { cerr<<"Unable to open file "< istream& List::fread(istream &in) { char buff[20]; int size; // can't use length because it is set by wipeOut and insert deleteAllValues(); Type newData; in >> size; in.getline(buff,20);// clear out the return at end of line with size ListIterator next(*this); next.init(); for(int i = 1;i<=size;i++) { Type val; in>>val; next.addAfter(val); next++; } return in; } template void List::removeValue(const Type &val) { ListIterator *next = genIterator(); if (next->locate(val)) next->removeCurrent(); } template ListIterator* List::genIterator() { ListIterator* returnVal = new ListIterator(*this); return returnVal; } //************* code for ShallowList *********** template ShallowList::ShallowList(Link *p,int sz) { _size = sz; ptrToFirstItem = new RCPtr(p); } //************ code for ListIterator ********** template ListIterator ListIterator::spawn() { static ShallowList L(current,theList._size-_pos); ListIterator result(L); return result; } template ListIterator::ListIterator (List &list) :theList(list) { init(); } template int ListIterator::init() { previous = NULL; current = theList.ptrToFirstItem->data; _pos = 1; return current !=NULL; } template Type& ListIterator::operator() (){ static Type errorDump; if(current !=NULL) return current->value(); else { cerr <<"current item is NULL\n"; return errorDump; } } template Type& ListIterator::moveTo(int i) { static Type errorDump; if(i<=0||i>theList._size+1) { cerr<<"Subscript "<getNext()) { previous = current; current = current->getNext(); } } if (current) return current->value(); else return errorDump; } template void ListIterator::operator = (const Type &val){ assert(current != NULL); current ->value() = val; } template void ListIterator::moveToNext() { previous = current; current = current->getNext(); _pos++; } template int ListIterator::operator ++() { if(current == NULL) { if(previous ==NULL) { current = theList.ptrToFirstItem->data; _pos = 1; } else current = previous->getNext(); } else moveToNext(); return current !=NULL; } template int ListIterator::operator ++(int) { if(current == NULL) { if(previous ==NULL) { current = theList.ptrToFirstItem->data; _pos = 1; } else current = previous->getNext(); } else moveToNext(); return current !=NULL; } template void ListIterator::addBefore(const Type &val) { if (previous) { previous = previous->insert(val); theList._size++; } else { theList.List::add(val);// add at beginning of list previous = theList.ptrToFirstItem->data; current = previous->getNext(); } _pos++; } template void ListIterator::addAfter(const Type &val) { if (current != NULL) { current->insert(val); theList._size++; } else if(previous != NULL) { current = previous->insert(val); theList._size++; } else theList.List::add(val); } template int ListIterator::locate(const Type &val) { return locateNextAfter(0,val); } template int ListIterator::locateNextAfter(int after,const Type &val) { after++; if(after<=0||after>theList._size+1) { cerr<<"Subscript "<value() == val) return _pos; moveToNext(); } return 0; } template int ListIterator::operator !() { if(current == NULL) if(previous != NULL) current = previous->getNext(); return current != NULL; } template ListIterator::operator int () { if(current == NULL) if(previous != NULL) current = previous->getNext(); return current != NULL; } template void ListIterator::removeCurrent() { // cout<<"In ListIterator::removeCurrent... removing "<value()<data = current->getNext(); delete current; } else // not the first item in the list previous->removeNext(); theList._size--; current =NULL; } //************ OrderedIterator code ************** template int OrderedIterator::locate(const Type &val) { init(); while (current && current->value() <= val) { if (current->value() == val) return _pos; moveToNext(); } return 0; } //************ OrderedList code ******************* template ListIterator* OrderedList::genIterator() { ListIterator* returnVal = new OrderedIterator(*this); return returnVal; } template int OrderedList::readAndOrder(const char* fName) { ifstream in (fName,ios::in); if (!in) { cerr<<"Unable to open file "< istream& OrderedList::readAndOrder(istream &in) { char buff[20]; int size; // can't use length because it is set by wipeOut and insert deleteAllValues(); Type newData; in >> size; in.getline(buff,20);// clear out the return at end of line with size OrderedIterator next(*this); for(int i = 1;i<=size;i++) { Type val; in>>val; if(!next.locate(val))//could just call insert here but is less efficient next.addBefore(val);// since insert must create the iterator for each // call to insert. } return in; } class IntList :public List{}; #endif