#ifndef DLL_H_ #define DLL_H_ 1 // Oldham, Jeffrey D. // 2000Mar13 // CS1321 // Modified by: // Massingill, Berna L. // 2000 Apr 05 // Doubly-Linked List Implementation // This class implements a doubly-linked list. Each link is allocatd // from dynamic memory. The list is represented as a circular-linked // list with a sentinel link. // Templatized and modified to include an iterator class; comments // with "****" indicate changes. #include #include // has NULL #include // has assert() template // **** added to "templatize" class class dll { public: class iterator; // **** "forward" declaration (needed // so "link" class knows "iterator" // is also a class). private: // **** nested "link" class private class link { private: friend class iterator; // iterator, dll classes need access to friend class dll; // link class private parts item_type itm; link * prev; // pointers to other links link * next; }; public: class iterator { // **** new nested class for iterator private: friend class dll; // dll class needs access to iterator // class private parts public: // Constructors. // Post: returns null iterator. iterator(void) { linkPtr = NULL; } // Forward and backward traversal. // Prefix increment (++p). // Pre: current object does not point to past-end. // Post: current object points to next element of list. // returns updated current object. iterator& operator++(void) { linkPtr = linkPtr->next; return *this; } // Postfix increment (p++). // Pre: current object does not point to past-end. // Post: current object points to next element of list. // returns initial value of current object. // Note the unused "int" parameter -- this is how the compiler // distinguishes between the prefix and postfix functions. iterator operator++(int) { iterator answer = *this; linkPtr = linkPtr->next; return answer; } // Prefix decrement (--p). // Pre: current object does not point to first element of list. // Post: current object points to previous element of list. // returns updated current object. iterator& operator--(void) { linkPtr = linkPtr->prev; return *this; } // Postfix decrement (p--). // Pre: current object does not point to first element of list. // returns initial value of current object. // Note the unused "int" parameter -- this is how the compiler // distinguishes between the prefix and postfix functions. iterator operator--(int) { iterator answer = *this; linkPtr = linkPtr->prev; return answer; } // Member access. // Pre: current object points to a list element. // Post: returns reference to element. item_type & operator*(void) const { return linkPtr->itm; } // Pre: current object points to a list element. // Post: returns pointer to element. // (This function would be useful if, e.g., we were making // a list of pairs and wanted to use the syntax pos->first.) item_type * operator->(void) const { return &(operator*()); } // Comparison operators. friend bool operator==(const iterator & p1, const iterator & p2) { return p1.linkPtr == p2.linkPtr; } friend bool operator!=(const iterator & p1, const iterator & p2) { return !(p1 == p2); } private: link * linkPtr; // iterator contains pointer to link // (This constructor is needed by some other member functions.) // Post: returns iterator equivalent of p. iterator(link * p) { linkPtr = p; } }; // end of nested iterator class // ---- Main dll class ---- // Constructor. dll(void) { create(); return; } // Copy constructor. dll(const dll & d) { copy(d); return; } // Assignment operator. dll& operator=(const dll & d) { if (this != &d) { destroy(); copy(d); } return *this; } // Destructor. ~dll(void) { // Delete all the links. destroy(); } // Insert the item before the specified position. // Post: an element with value "i" has been added before *pos. // returns iterator pointing to newly-added element. // **** first parameter, return type now iterators, not link pointers. iterator insert(const iterator & pos, const item_type & i) { link * n = new link; n->itm = i; link * afterInsert = pos.linkPtr; // Change new link's pointers. n->prev = afterInsert->prev; n->next = afterInsert; // Change the surrounding links' pointers. n->next->prev = n; n->prev->next = n; return iterator(n); } // Delete the specified element. // Pre: *pos is not the sentinel. // Post: *pos has been removed from the list. // returns iterator pointing to element following *pos. // **** parameter, return type now iterators, not link pointers. iterator erase(const iterator & pos) { link * n = pos.linkPtr; iterator answer(n->next); // Change the surrounding links' pointers. n->prev->next = n->next; n->next->prev = n->prev; // Change new link's pointers. (not actually necessary) n->prev = 0; n->next = 0; delete n; return answer; } // Get start of list (analogous to STL classes' begin()). // Post: returns iterator pointing to first element in list, // or to sentinel if list is empty. // **** function now returns iterator, not link pointer, // and we provide two versions, one "const" and one not. iterator begin(void) { return iterator(sentinel->next); } const iterator begin(void) const { return iterator(sentinel->next); } // Get past-end of list (analogous to STL classes' end()). // Post: returns iterator pointing to sentinel. // **** function now returns iterator, not link pointer, // and we provide two versions, one "const" and one not. iterator end(void) { return iterator(sentinel); } const iterator end(void) const { return iterator(sentinel); } // **** pred(), succ() functions no longer needed. private: link * sentinel; // sentinel (dummy) link, always present // Create an empty list. // Pre: sentinel does not point to anything; no "link" objects are // allocated for this list. // Post: sentinel points to the "sentinel" node, which is the only // link in the list. void create(void) { sentinel = new link; // sentinel->itm need not be set sentinel->prev = sentinel; sentinel->next = sentinel; return; } // Destroy this list. // Pre: sentinel points to sentinel link for list. // Post: all allocated "link" objects have been freed. void destroy(void) { while (sentinel->next != sentinel) erase(sentinel->next); delete sentinel; } // Copy the given list into this one. // Pre: sentinel does not point to anything; no "link" objects are // allocated for this list. // Post: list is a copy of list "d". void copy(const dll & d) { create(); for (link * pos = d.sentinel->next; pos != d.sentinel; pos = pos->next) insert(sentinel, pos->itm); return; } // Output operator. //template //friend ostream & operator << (ostream & o, const dll & d) { friend ostream & operator << (ostream & o, const dll & d) { for (iterator p = d.begin(); p != d.end(); ++p) o << *p << ' '; return o; } }; #endif // DLL_H_