// List.h // // A class list similar to the STL container list. // Version 1.1 // // Included from Version 1.0: // list(), ~list(), back(), push_back(e), pop_back() // // New in this version: // iterators, constant iterators // begin, end, cbegin, cend // insert, erase #ifndef _List_h_ #define _List_h_ namespace CS142 { template class list; template class ConstListIterator; template class ListNode // T is the type of element stored in the list. { public: ListNode() : element(), next(nullptr), previous(nullptr) {} ListNode(const T& e, ListNode* next0, ListNode* previous0): element(e), next(next0), previous(previous0) {} ~ListNode() { next = previous = nullptr; } T element; ListNode * next; ListNode * previous; }; template class ListIterator // T is the type of element stored in the list. { friend class list; friend class ConstListIterator; public: ListIterator() : current_node_(nullptr) {} T& operator*() const { return current_node_->element; } T* operator->() const { return &(current_node_->element); } bool operator==(const ListIterator & rhs) const { return (current_node_ == rhs.current_node_); } bool operator!=(const ListIterator & rhs) const { return (current_node_ != rhs.current_node_); } ListIterator& operator++(); // prefix version (++itr) ListIterator& operator--(); ListIterator operator++(int); // postfix version (itr++) ListIterator operator--(int); private: explicit ListIterator(ListNode* p) : current_node_(p) {} ListNode* current_node_; // points to the node that contains the element that the // iterator currently points to }; template inline ListIterator& ListIterator::operator++() // prefix version (++itr) { current_node_ = current_node_->next; return *this; } template inline ListIterator & ListIterator::operator--() // prefix version (--itr) { current_node_ = current_node_->previous; return *this; } template inline ListIterator ListIterator::operator++(int) // postfix version (itr++) { auto original_itr = *this; current_node_ = current_node_->next; return original_itr; } template inline ListIterator ListIterator::operator--(int) // postfix version (itr++) { auto original_itr = *this; current_node_ = current_node_->previous; return original_itr; } template class ConstListIterator // T is the type of element stored in the list. { friend class list; public: ConstListIterator() : current_node_(nullptr) {} ConstListIterator(const ListIterator& itr) : current_node_(itr.current_node_) {} const T& operator*() const { return current_node_->element; } const T* operator->() const { return &(current_node_->element); } bool operator==(const ConstListIterator& rhs) const { return (current_node_ == rhs.current_node_); } bool operator!=(const ConstListIterator& rhs) const { return (current_node_ != rhs.current_node_); } ConstListIterator& operator++(); // prefix version (++itr) ConstListIterator& operator--(); ConstListIterator operator++(int); // postfix version (itr++) ConstListIterator operator--(int); private: explicit ConstListIterator(ListNode* p) : current_node_(p) {} ListNode* current_node_; // points to the node that contains the element that the // iterator currently points to }; template inline ConstListIterator& ConstListIterator::operator++() // prefix version (++itr) { current_node_ = current_node_->next; return *this; } template inline ConstListIterator& ConstListIterator::operator--() // prefix version (--itr) { current_node_ = current_node_->previous; return *this; } template inline ConstListIterator ConstListIterator::operator++(int) // postfix version (itr++) { auto original_itr = *this; current_node_ = current_node_->next; return original_itr; } template inline ConstListIterator ConstListIterator::operator--(int) // postfix version (itr++) { auto original_itr = *this; current_node_ = current_node_->previous; return original_itr; } template class list // T is the type of element stored in the list. { public: using iterator = ListIterator; using const_iterator = ConstListIterator; list(); ~list(); int size() const { return size_; } T& back() { return head_node_->previous->element; } const T& back() const { return head_node_->previous->element; } void push_back(const T & new_element); void pop_back(); // void test_print() const; iterator begin() { return iterator(head_node_->next); } iterator end() { return iterator(head_node_); } const_iterator begin() const { return const_iterator(head_node_->next); } const_iterator end() const { return const_iterator(head_node_); } const_iterator cbegin() const { return const_iterator(head_node_->next); } const_iterator cend() const { return const_iterator(head_node_); } iterator insert(const_iterator itr, const T& new_element); iterator erase(const_iterator itr); private: ListNode* head_node_; int size_; }; template inline list::list() : size_(0) { head_node_ = new ListNode; head_node_->next = head_node_->previous = head_node_; } template inline list::~list() { while (size_ != 0) { pop_back(); } delete head_node_; } template void list::push_back(const T& new_element) { auto last_node = head_node_->previous; auto new_node = new ListNode(new_element, head_node_, last_node); // finish linking new node to list last_node->next = new_node; head_node_->previous = new_node; ++size_; } template void list::pop_back() { auto last_node = head_node_->previous; auto new_last_node = last_node->previous; // modify the list to skip the last node new_last_node->next = head_node_; head_node_->previous = new_last_node; delete last_node; --size_; } //template //void list::test_print() const //{ // for (ListNode * node = head_node_->next; // node != head_node_; // node = node->next) { // cout << node->element << ' '; // } // cout << endl; //} template typename list::iterator list::insert( const_iterator itr, const T& new_element) { auto next_node = itr.current_node_; auto previous_node = next_node->previous; auto new_node = new ListNode(new_element, next_node, previous_node); previous_node->next = new_node; next_node->previous = new_node; ++size_; return iterator(new_node); } template typename list::iterator list::erase( const_iterator itr) { auto target_node = itr.current_node_; auto previous_node = target_node->previous; auto next_node = target_node->next; // modify the list to skip the target node previous_node->next = next_node; next_node->previous = previous_node; delete target_node; --size_; return iterator(next_node); } } // namespace CS142 #endif