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