// File: LinkedList.h // Linked List class with List Iterator class #ifndef _LinkedList_ #define _LinkedList_ #include #include using namespace std; // Need to prototype template classes if they are to be friends template class LinkedList; template class ListIterator; /* // and also the friend...note <> in header declaration of << template ostream& operator<<(ostream&,LinkedList); */ template class node { private: node(eltType info= 0, node* link = NULL ) : data(info), next(link) {}; eltType data; node* next; friend class LinkedList; friend class ListIterator; }; template class LinkedList { public: // Construct empty LinkedList LinkedList(); // Construct deep copy of another LinkedList LinkedList(LinkedList&); // destroy LinkedList ~LinkedList(); // Assign another LinkedList to this LinkedList; deep copy LinkedList& operator=(const LinkedList&); // Is the LinkedList empty? bool empty(); bool find(eltType); // Ordered insert/remove void orderedInsert(eltType); void remove(eltType); private: // linked list pointer node* head; // Get a copy of a (deep) node node* copy(node *); // Free nodes of a linked list void destroy(node *); // Needed to use a list iterator friend class ListIterator; }; template ostream& operator<<(ostream &os,const LinkedList &l); // Set up an iterator; // an object that provides a pointer to a linked list (in this case) template class ListIterator { public: // Construc a List Iterator ListIterator(const LinkedList &l); // Set curr to point at the first node of itr void start(); // Is curr null? bool more(); // Go to curr->next void next(); // Get the value out of curr's node eltType value(); private: const LinkedList &itr; node *curr; }; // Construct empty LinkedList template LinkedList::LinkedList() : head(NULL) {} // Copy constructor. copy() does the deep copy template LinkedList::LinkedList(LinkedList &cl) {head = copy( cl.head );} // Free all nodes template LinkedList::~LinkedList() {destroy(head);} // Assignment operator: copy() does the deep copy template LinkedList &LinkedList::operator =(const LinkedList& cl) { if (this != &cl) { destroy(head); head = copy(cl.head); } return *this; } // Place x into the list in order template void LinkedList::orderedInsert(eltType x) { if (empty() || x < head->data) assert(head=new node(x,head)); else // start at 2nd node...already checked first node { node* p = head -> next; // head; node* trailp = head; // NULL; while (p != NULL && x > p->data) { trailp = p; p = p->next; } assert((trailp->next = new node(x,p)) != NULL); } } // Is this element in the linked list? template bool LinkedList::find(eltType x) { node *p = head; while (p != NULL && p->data != x) p = p->next; return (p != NULL && p->data == x); } // Inline: Look into this. template inline bool LinkedList::empty() {return (head == NULL);} // Remove a node in an ordered list // Pre: Node will be found template void LinkedList::remove(eltType x) { assert( !empty() ); node* p = head; node* trailp = NULL; while ( p != NULL && p->data != x ) { trailp = p; p = p->next; } assert(p != NULL); // x is not in the LinkedList if (p == head) head = head->next; // x is first in the LinkedList else trailp->next = p->next; // x is farther down in the LinkedList delete p; } // Remove all nodes in the linked list, starting at l template void LinkedList::destroy(node *l) { while (l != NULL) { node *doomed = l; l = l->next; delete doomed; } } // The deep copy. Copy the source list l, one node at a time template node* LinkedList::copy(node *l) { node* first = NULL; // ptr to beginning of copied LinkedList node* last = NULL; // ptr to last item insert in the copy if (l != NULL) { assert((first=last=new node(l->data,NULL)) != NULL); for (node* source=l->next;source!=NULL; source=source->next,last=last->next) { last->next = new node(source->data,NULL); assert(last->next); } } return first; } // Output a linked list, using a list iterator template ostream& operator<<(ostream &os,const LinkedList &l) { ListIterator lt(l); for (lt.start(); lt.more(); lt.next()) os << lt.value() << " "; return os; } /* **************************************************************** ************** List Iterator Implementations ******************* ****************************************************************/ // Construct a list iterator. It consists of: // a reference to a linked list object // a pointer to the actual list, initially pointing to its head template ListIterator::ListIterator(const LinkedList &l): itr(l),curr(l.head) {} // Set curr to point at itr's head template void ListIterator::start(void) {curr = itr.head;} // Is curr at the end of the list? template bool ListIterator::more(void) {return curr != NULL;} // Move curr to next node template void ListIterator::next(void) {assert( curr != NULL ); curr = curr->next; } // Return data in curr's node. Regardless of assert(), this // function shouldn't be called until making sure more() returns true template eltType ListIterator::value(void) {assert( curr != NULL ); return curr->data; } #endif