C++ pleae /// Your welcome DoublyLinkedList() { this->head_ = nullptr; this->tail_ = nullptr; this->size_ = 0; } /// Copy Constructor DoublyLinkedList(DoublyLinkedList& other) { for (auto it = other.begin(); it!= other.end(); ++it) { this->push_back(*it); } } /// DTOR: Your welcome ~DoublyLinkedList() { this->clear(); } /** * Clear the list and assign the same value, count times. * If count was 5, T was int, and value was 3, * we'd end up with a list like {3, 3, 3, 3, 3} */ void assign(size_t count, const T& value) { this->clear(); for (size_t i = 0; i < count; ++i) { this->push_back(value); } } /** * Clear the list and assign values from another list. * The 'first' iterator points to the first item copied from the other list. * The 'last' iterator points to the last item copied from the other list. * * Example: * Suppose we have a source list like {8, 4, 3, 2, 7, 1} * Suppose first points to the 4 * Suppose last points to the 7 * We should end up with our list becoming: {4, 3, 2, 7} * * If the user code sends out-of-order iterators, * just copy from 'first' to the end of the source list * Example: first=7, last=4 from the list above would give us: * {7, 1} */ void assign(Iterator first, Iterator last) { this->clear(); Iterator it; for (it = first; it!= last; ++it) { this->push_back(*it); } if (it != nullptr && it->next == last) { this->push_back(*last); } } /// Return a pointer to the head node, if any Node<T>* head() { return head_; } /// Return a pointer to the tail node, if any Node<T>* tail() { return tail_; } /** * Return an iterator that points to the head of our list */ Iterator begin() { return Iterator(this->head_); } /** * Return an iterator that points to the last element (tail) of our list */ Iterator last() { return Iterator(this->tail_); } /** * Should return an iterator that represents being past the end of our nodes, * or just that we are finished. * You can make this a nullptr or use some other scheme of your choosing, * as long as it works with the logic of the rest of your implementations. */ Iterator end() { return Iterator(nullptr); } /** * Returns true if our list is empty */ bool empty() const { return this->size_ == 0; } /** * Returns the current size of the list * Should finish in constant time! * (keep track of the size elsewhere) */ size_t size() const { return 0; } /** * Clears our entire list, making it empty * Remember: All removal operations should be memory-leak free. */ void clear() { size_ = 0; Node<T> *node = this->head_; while (node!= nullptr) { Node<T> *next = node->next_; delete node; node = next; } this->head_ = nullptr; this->tail_ = nullptr; } /** * Insert an element after the node pointed to by the pos Iterator * * If the list is currently empty, * ignore the iterator and just make the new node at the head/tail (list of length 1). * * If the incoming iterator is this->end(), insert the element at the tail * * Should return an iterator that points to the newly added node * * To avoid repeated code, it.