#ifndef dslist_h_ #define dslist_h_ // A simplified implementation of the STL list container class, // including the iterator, but not the const_iterators. Three // separate classes are defined: a Node class, an iterator class, and // the actual list class. The underlying list is doubly-linked, but // there is no dummy head node and the list is not circular. #include // ----------------------------------------------------------------- // NODE CLASS template class Node { public: Node() : next_(NULL), prev_(NULL) {} Node(const T& v) : value_(v), next_(NULL), prev_(NULL) {} // REPRESENTATION T value_; Node* next_; Node* prev_; }; // A "forward declaration" of this class is needed template class dslist; // ----------------------------------------------------------------- // LIST ITERATOR template class list_iterator { public: // default constructor, copy constructor, assignment operator, & destructor list_iterator(Node* p=NULL) : ptr_(p) {} // NOTE: the implicit compiler definitions of the copy constructor, // assignment operator, and destructor are correct for this class // dereferencing operator gives access to the value at the pointer T& operator*() { return ptr_->value_; } // increment & decrement operators list_iterator& operator++() { // pre-increment, e.g., ++iter ptr_ = ptr_->next_; return *this; } list_iterator operator++(int) { // post-increment, e.g., iter++ list_iterator temp(*this); ptr_ = ptr_->next_; return temp; } list_iterator& operator--() { // pre-decrement, e.g., --iter ptr_ = ptr_->prev_; return *this; } list_iterator operator--(int) { // post-decrement, e.g., iter-- list_iterator temp(*this); ptr_ = ptr_->prev_; return temp; } // the dslist class needs access to the private ptr_ member variable friend class dslist; // Comparions operators are straightforward bool operator==(const list_iterator& r) const { return ptr_ == r.ptr_; } bool operator!=(const list_iterator& r) const { return ptr_ != r.ptr_; } private: // REPRESENTATION Node* ptr_; // ptr to node in the list }; // ----------------------------------------------------------------- // LIST CLASS DECLARATION // Note that it explicitly maintains the size of the list. template class dslist { public: // default constructor, copy constructor, assignment operator, & destructor dslist() : head_(NULL), tail_(NULL), size_(0) {} dslist(const dslist& old) { copy_list(old); } dslist& operator= (const dslist& old); ~dslist() { destroy_list(); } typedef list_iterator iterator; // simple accessors & modifiers unsigned int size() const { return size_; } bool empty() const { return head_ == NULL; } void clear() { destroy_list(); } // read/write access to contents const T& front() const { return head_->value_; } T& front() { return head_->value_; } const T& back() const { return tail_->value_; } T& back() { return tail_->value_; } // modify the linked list structure void push_front(const T& v); void pop_front(); void push_back(const T& v); void pop_back(); iterator erase(iterator itr); iterator insert(iterator itr, const T& v); iterator begin() { return iterator(head_); } iterator end() { return iterator(NULL); } private: // private helper functions void copy_list(const dslist& old); void destroy_list(); //REPRESENTATION Node* head_; Node* tail_; unsigned int size_; }; // ----------------------------------------------------------------- // LIST CLASS IMPLEMENTATION template dslist& dslist::operator= (const dslist& old) { // check for self-assignment if (&old != this) { destroy_list(); copy_list(old); } return *this; } template void dslist::push_front(const T& v) { } template void dslist::pop_front() { } template void dslist::push_back(const T& v) { Node* newp = new Node(v); // special case: initially empty list if (!tail_) { head_ = tail_ = newp; } else { // normal case: at least one node already newp->prev_ = tail_; tail_->next_ = newp; tail_ = newp; } ++size_; } template void dslist::pop_back() { } // do these lists look the same (length & contents)? template bool operator== (dslist& left, dslist& right) { if (left.size() != right.size()) return false; typename dslist::iterator left_itr = left.begin(); typename dslist::iterator right_itr = right.begin(); // walk over both lists, looking for a mismatched value while (left_itr != left.end()) { if (*left_itr != *right_itr) return false; left_itr++; right_itr++; } return true; } template bool operator!= (dslist& left, dslist& right){ return !(left==right); } template typename dslist::iterator dslist::erase(iterator itr) { assert (size_ > 0); --size_; iterator result(itr.ptr_->next_); // One node left in the list. if (itr.ptr_ == head_ && head_ == tail_) { head_ = tail_ = 0; } // Removing the head in a list with at least two nodes else if (itr.ptr_ == head_) { head_ = head_->next_; head_->prev_ = 0; } // Removing the tail in a list with at least two nodes else if (itr.ptr_ == tail_) { tail_ = tail_->prev_; tail_->next_ = 0; } // Normal remove else { itr.ptr_->prev_->next_ = itr.ptr_->next_; itr.ptr_->next_->prev_ = itr.ptr_->prev_; } delete itr.ptr_; return result; } template typename dslist::iterator dslist::insert(iterator itr, const T& v) { ++size_ ; Node* p = new Node(v); p->prev_ = itr.ptr_->prev_; p->next_ = itr.ptr_; itr.ptr_->prev_ = p; if (itr.ptr_ == head_) head_ = p; else p->prev_->next_ = p; return iterator(p); } template void dslist::copy_list(const dslist& old) { size_ = old.size_; // Handle the special case of an empty list. if (size_ == 0) { head_ = tail_ = 0; return; } // Create a new head node. head_ = new Node(old.head_->value_); // tail_ will point to the last node created and therefore will move // down the new list as it is built tail_ = head_; // old_p will point to the next node to be copied in the old list Node* old_p = old.head_->next_; // copy the remainder of the old list, one node at a time while (old_p) { tail_->next_ = new Node(old_p->value_); tail_->next_->prev_ = tail_; tail_ = tail_->next_; old_p = old_p->next_; } } template void dslist::destroy_list() { } #endif