#ifndef cs2list_h_ #define cs2list_h_ // A simplified implementation of a generic 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. // ----------------------------------------------------------------- // 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 cs2list; // ----------------------------------------------------------------- // LIST ITERATOR template class list_iterator { public: list_iterator() : ptr_(NULL) {} list_iterator(Node* p) : ptr_(p) {} list_iterator(list_iterator const& old) : ptr_(old.ptr_) {} ~list_iterator() {} list_iterator & operator=(const list_iterator & old) { ptr_ = old.ptr_; return *this; } // dereferencing operator gives access to the value at the pointer T& operator*() { return ptr_->value_; } // increment & decrement operators list_iterator & operator++() { ptr_ = ptr_->next_; return *this; } list_iterator operator++(int) { list_iterator temp(*this); ptr_ = ptr_->next_; return temp; } list_iterator & operator--() { ptr_ = ptr_->prev_; return *this; } list_iterator operator--(int) { list_iterator temp(*this); ptr_ = ptr_->prev_; return temp; } friend class cs2list; // Comparions operators are straightforward friend bool operator==(const list_iterator& l, const list_iterator& r) { return l.ptr_ == r.ptr_; } friend bool operator!=(const list_iterator& l, const list_iterator& r) { return l.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 cs2list { public: cs2list() : head_(NULL), tail_(NULL), size_(0) {} cs2list(const cs2list& old) { this->copy_list(old); } ~cs2list() { this->destroy_list(); } cs2list& operator= (const cs2list& old); unsigned int size() const { return size_; } bool empty() const { return head_ == NULL; } void clear() { this->destroy_list(); } void push_front(const T& v); void pop_front(); void push_back(const T& v); void pop_back(); const T& front() const { return head_->value_; } T& front() { return head_->value_; } const T& back() const { return tail_->value_; } T& back() { return tail_->value_; } typedef list_iterator iterator; iterator erase(iterator itr); iterator insert(iterator itr, T const& v); iterator begin() { return iterator(head_); } iterator end() { return iterator(NULL); } private: void copy_list(cs2list const & old); void destroy_list(); //REPRESENTATION Node* head_; Node* tail_; unsigned int size_; }; // ----------------------------------------------------------------- // LIST CLASS IMPLEMENTATION template cs2list& cs2list::operator= (const cs2list& old) { if (&old != this) { this->destroy_list(); this->copy_list(old); } return *this; } template void cs2list::push_back(const T& v) { Node* newp = new Node( v ); // special case: initially empty list if (!tail_) { head_ = tail_ = newp; } // normal case: at least one node already else { newp -> prev_ = tail_; tail_ -> next_ = newp; tail_ = newp; } ++size_; } template void cs2list::push_front(const T& v) { } template void cs2list::pop_back() { } template void cs2list::pop_front() { } template typename cs2list::iterator cs2list::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; } // insert BEFORE the node indicated by the iterator and return an iterator to the new node template typename cs2list::iterator cs2list::insert(iterator itr, T const& 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 cs2list::copy_list(cs2list const & 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 cs2list::destroy_list() { } #endif