LinkedList.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #pragma once
  2. #include <iostream>
  3. // Forward declaration of LinkedListNode
  4. template <typename T> class LinkedListNode;
  5. class LinkedListException {};
  6. /// <summary>
  7. /// Class representing a linked list
  8. /// </summary>
  9. /// <typeparam name="T">Value type</typeparam>
  10. template <typename T> class LinkedList {
  11. bool isCircular;
  12. LinkedListNode<T>* start;
  13. /// <summary>
  14. /// Copies the linked list to another instance
  15. /// </summary>
  16. /// <param name="list">Pointer to original linked list</param>
  17. LinkedList(const LinkedList& list);
  18. /// <summary>
  19. /// Assignment operator override
  20. /// </summary>
  21. /// <param name="list">The original linked list to be copied</param>
  22. /// <returns>The copied linked list</returns>
  23. LinkedList& operator =(const LinkedList& list);
  24. public:
  25. LinkedList();
  26. ~LinkedList();
  27. /// <summary>
  28. /// Get the starting node of the linked list
  29. /// </summary>
  30. /// <returns>First node of the list</returns>
  31. LinkedListNode<T>* getStart();
  32. /// <summary>
  33. /// Delete the first item
  34. /// </summary>
  35. void deleteFirst();
  36. /// <summary>
  37. /// Delete the item following the node
  38. /// </summary>
  39. /// <param name="ptr">The node before the item to delete</param>
  40. void deleteAfter(LinkedListNode<T>* ptr);
  41. /// <summary>
  42. /// Insert some value into the new node in the beginning
  43. /// </summary>
  44. /// <param name="data">The value to be inserted</param>
  45. void insertFirst(const T& value);
  46. /// <summary>
  47. /// Insert some value after the node
  48. /// </summary>
  49. /// <param name="ptr">The node after which the value shall be inserted</param>
  50. /// <param name="data">The value to be inserted</param>
  51. void insertAfter(LinkedListNode<T>* ptr, const T& value);
  52. /// <summary>
  53. /// Make the linked list circular (looped)
  54. /// </summary>
  55. void makeCircular();
  56. /// <summary>
  57. /// Output operator override
  58. /// </summary>
  59. /// <typeparam name="T">Some type</typeparam>
  60. /// <param name="out">Outbound stream</param>
  61. /// <param name="list">Linked list to be printed out</param>
  62. /// <returns>Outbound stream containing serialized values of the linked list</returns>
  63. template <typename U> friend std::ostream& operator <<(std::ostream& out, LinkedList<U>& list);
  64. };
  65. // Implementation of LinkedList
  66. template <typename T> LinkedList<T>::LinkedList()
  67. : start(nullptr), isCircular(false) {}
  68. template <typename T> LinkedList<T>::~LinkedList() {
  69. if (isCircular) {
  70. LinkedListNode<T>* current = start;
  71. while (current->_next != start) {
  72. current = current->_next;
  73. }
  74. current->_next = nullptr;
  75. }
  76. while (start) {
  77. deleteFirst();
  78. }
  79. }
  80. template <typename T> LinkedListNode<T>* LinkedList<T>::getStart() {
  81. return start;
  82. }
  83. template <typename T> void LinkedList<T>::deleteFirst() {
  84. if (start) {
  85. LinkedListNode<T>* temp = start->_next;
  86. delete start;
  87. start = temp;
  88. }
  89. else {
  90. throw LinkedListException();
  91. }
  92. }
  93. template <typename T> void LinkedList<T>::deleteAfter(LinkedListNode<T>* ptr) {
  94. if (ptr && ptr->_next) {
  95. if (ptr->_next == start) {
  96. LinkedListNode<T>* temp = ptr->_next;
  97. ptr->_next = ptr->_next->_next;
  98. delete temp;
  99. start = ptr->_next;
  100. }
  101. else {
  102. LinkedListNode<T>* temp = ptr->_next;
  103. ptr->_next = ptr->_next->_next;
  104. delete temp;
  105. }
  106. }
  107. else {
  108. throw LinkedListException();
  109. }
  110. }
  111. template <typename T> void LinkedList<T>::insertFirst(const T& value) {
  112. LinkedListNode<T>* second = start;
  113. start = new LinkedListNode<T>(value, second);
  114. }
  115. template <typename T> void LinkedList<T>::insertAfter(LinkedListNode<T>* ptr, const T& value) {
  116. if (ptr) {
  117. LinkedListNode<T>* temp = ptr->_next;
  118. ptr->_next = new LinkedListNode<T>(value, temp);
  119. }
  120. }
  121. template <typename T> std::ostream& operator<<(std::ostream& out, LinkedList<T>& list) {
  122. LinkedListNode<T>* ptr = list.getStart();
  123. if (!ptr) {
  124. out << "EMPTY ";
  125. }
  126. else {
  127. do {
  128. out << ptr->getValue() << ' ';
  129. ptr = ptr->getNext();
  130. } while (ptr && ptr != list.getStart());
  131. }
  132. return out;
  133. }
  134. template <typename T> void LinkedList<T>::makeCircular() {
  135. if (start == nullptr) {
  136. return;
  137. }
  138. LinkedListNode<T>* current = start;
  139. while (current->_next != nullptr) {
  140. current = current->_next;
  141. }
  142. current->_next = start;
  143. isCircular = true;
  144. }