#pragma once #include // Forward declaration of LinkedListNode template class LinkedListNode; class LinkedListException {}; /// /// Class representing a linked list /// /// Value type template class LinkedList { bool isCircular; LinkedListNode* start; /// /// Copies the linked list to another instance /// /// Pointer to original linked list LinkedList(const LinkedList& list); /// /// Assignment operator override /// /// The original linked list to be copied /// The copied linked list LinkedList& operator =(const LinkedList& list); public: LinkedList(); ~LinkedList(); /// /// Get the starting node of the linked list /// /// First node of the list LinkedListNode* getStart(); /// /// Delete the first item /// void deleteFirst(); /// /// Delete the item following the node /// /// The node before the item to delete void deleteAfter(LinkedListNode* ptr); /// /// Insert some value into the new node in the beginning /// /// The value to be inserted void insertFirst(const T& value); /// /// Insert some value after the node /// /// The node after which the value shall be inserted /// The value to be inserted void insertAfter(LinkedListNode* ptr, const T& value); /// /// Make the linked list circular (looped) /// void makeCircular(); /// /// Output operator override /// /// Some type /// Outbound stream /// Linked list to be printed out /// Outbound stream containing serialized values of the linked list template friend std::ostream& operator <<(std::ostream& out, LinkedList& list); }; // Implementation of LinkedList template LinkedList::LinkedList() : start(nullptr), isCircular(false) {} template LinkedList::~LinkedList() { if (isCircular) { LinkedListNode* current = start; while (current->_next != start) { current = current->_next; } current->_next = nullptr; } while (start) { deleteFirst(); } } template LinkedListNode* LinkedList::getStart() { return start; } template void LinkedList::deleteFirst() { if (start) { LinkedListNode* temp = start->_next; delete start; start = temp; } else { throw LinkedListException(); } } template void LinkedList::deleteAfter(LinkedListNode* ptr) { if (ptr && ptr->_next) { if (ptr->_next == start) { LinkedListNode* temp = ptr->_next; ptr->_next = ptr->_next->_next; delete temp; start = ptr->_next; } else { LinkedListNode* temp = ptr->_next; ptr->_next = ptr->_next->_next; delete temp; } } else { throw LinkedListException(); } } template void LinkedList::insertFirst(const T& value) { LinkedListNode* second = start; start = new LinkedListNode(value, second); } template void LinkedList::insertAfter(LinkedListNode* ptr, const T& value) { if (ptr) { LinkedListNode* temp = ptr->_next; ptr->_next = new LinkedListNode(value, temp); } } template std::ostream& operator<<(std::ostream& out, LinkedList& list) { LinkedListNode* ptr = list.getStart(); if (!ptr) { out << "EMPTY "; } else { do { out << ptr->getValue() << ' '; ptr = ptr->getNext(); } while (ptr && ptr != list.getStart()); } return out; } template void LinkedList::makeCircular() { if (start == nullptr) { return; } LinkedListNode* current = start; while (current->_next != nullptr) { current = current->_next; } current->_next = start; isCircular = true; }