DoublyLinkedList.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. // Project: Doubly_Linked_List.cbp
  2. // File : DoublyLinkedList.h
  3. #ifndef DOUBLYLINKEDLIST_H
  4. #define DOUBLYLINKEDLIST_H
  5. #include <iostream>
  6. #include "DoublyNode.h"
  7. template <typename T>
  8. class DoublyLinkedList
  9. {
  10. private:
  11. int m_count;
  12. public:
  13. // The first node in the list
  14. // or null if empty
  15. DoublyNode<T> * Head;
  16. // The last node in the list
  17. // or null if empty
  18. DoublyNode<T> * Tail;
  19. // Constructor
  20. DoublyLinkedList();
  21. // Get() operation
  22. DoublyNode<T> * Get(int index);
  23. // Insert() operation
  24. void InsertHead(T val);
  25. void InsertTail(T val);
  26. void Insert(int index, T val);
  27. // Search() operation
  28. int Search(T val);
  29. // Remove() operation
  30. void RemoveHead();
  31. void RemoveTail();
  32. void Remove(int index);
  33. // Additional operation
  34. int Count();
  35. void PrintList();
  36. void PrintListBackward();
  37. };
  38. template <typename T>
  39. DoublyLinkedList<T>::DoublyLinkedList()
  40. : m_count(0), Head(NULL), Tail(NULL) {}
  41. template <typename T>
  42. DoublyNode<T> * DoublyLinkedList<T>::Get(int index)
  43. {
  44. // Check if the index is out of bound
  45. if(index < 0 || index > m_count)
  46. return NULL;
  47. // Start from the Head
  48. DoublyNode<T> * node = Head;
  49. // Iterate through the linked list elements
  50. // until it finds the selected index
  51. for(int i = 0; i < index; ++i)
  52. {
  53. node = node->Next;
  54. }
  55. // Simply return the node result
  56. return node;
  57. }
  58. template <typename T>
  59. void DoublyLinkedList<T>::InsertHead(T val)
  60. {
  61. // Create a new Node
  62. DoublyNode<T> * node = new DoublyNode<T>(val);
  63. // The current Head will no longer become a Head
  64. // so the Next pointer of the new Node will
  65. // point to the current Head
  66. node->Next = Head;
  67. // If the current Head is exist,
  68. // the previous pointer of the current Head
  69. // should point to the node
  70. if(Head != NULL)
  71. Head->Previous = node;
  72. // The new Node now become the Head
  73. Head = node;
  74. // If the linked list is empty
  75. // The Tail is also the Head
  76. if(m_count == 0)
  77. Tail = Head;
  78. // One element is added
  79. m_count++;
  80. }
  81. template <typename T>
  82. void DoublyLinkedList<T>::InsertTail(T val)
  83. {
  84. // If the linked list is empty,
  85. // just simply invoke InsertHead()
  86. if(m_count == 0)
  87. {
  88. InsertHead(val);
  89. return;
  90. }
  91. // Create a new Node
  92. DoublyNode<T> * node = new DoublyNode<T>(val);
  93. // The current Tail will no longer become a Tail
  94. // so the Next pointer of the current Tail will
  95. // point to the new node
  96. Tail->Next = node;
  97. // Also, the previous pointer of the new node
  98. // should point to the current Tail
  99. node->Previous = Tail;
  100. // The new Node now become the Tail
  101. Tail = node;
  102. // One element is added
  103. m_count++;
  104. }
  105. template <typename T>
  106. void DoublyLinkedList<T>::Insert(int index, T val)
  107. {
  108. // Check if the index is out of bound
  109. if(index < 0 || index > m_count)
  110. return;
  111. // If inserting a new Head
  112. if(index == 0)
  113. {
  114. InsertHead(val);
  115. return;
  116. }
  117. // If inserting a new Tail
  118. else if(index == m_count)
  119. {
  120. InsertTail(val);
  121. return;
  122. }
  123. // Start to find previous node
  124. // from the Head
  125. DoublyNode<T> * prevNode = Head;
  126. // Traverse the elements until
  127. // the selected index is found
  128. for(int i = 0; i < index - 1; ++i)
  129. {
  130. prevNode = prevNode->Next;
  131. }
  132. // Create the next node which is
  133. // the element after previous node
  134. DoublyNode<T> * nextNode = prevNode->Next;
  135. // Create a new node
  136. DoublyNode<T> * node = new DoublyNode<T>(val);
  137. // Insert this new node between
  138. // the previous node and the next node
  139. node->Next = nextNode;
  140. node->Previous = prevNode;
  141. prevNode->Next = node;
  142. nextNode->Previous = node;
  143. // One element is added
  144. m_count++;
  145. }
  146. template <typename T>
  147. int DoublyLinkedList<T>::Search(T val)
  148. {
  149. // If LinkedList is empty,
  150. // just return NOT_FOUND
  151. if(m_count == 0)
  152. return -1;
  153. // Need to count the index
  154. int index = 0;
  155. // Traverse from the Head node
  156. DoublyNode<T> * node = Head;
  157. // Traverse until the selected value
  158. // is matched with the value
  159. // of the current position,
  160. while(node->Value != val)
  161. {
  162. index++;
  163. node = node->Next;
  164. // This will happen
  165. // if the selected value
  166. // is not found
  167. if(node == NULL)
  168. {
  169. return -1;
  170. }
  171. }
  172. return index;
  173. }
  174. template <typename T>
  175. void DoublyLinkedList<T>::RemoveHead()
  176. {
  177. // Do nothing if list is empty
  178. if(m_count == 0)
  179. return;
  180. // Save the current Head
  181. // to a new node
  182. DoublyNode<T> * node = Head;
  183. // Point the Head Pointer
  184. // to the element next to the current Head
  185. Head = Head->Next;
  186. // Now it's safe to remove
  187. // the first element
  188. delete node;
  189. // If there's still any element in the list,
  190. // the previous pointer of the Head
  191. // should point to NULL
  192. if(Head != NULL)
  193. Head->Previous = NULL;
  194. // One element is removed
  195. m_count--;
  196. }
  197. template <typename T>
  198. void DoublyLinkedList<T>::RemoveTail()
  199. {
  200. // Do nothing if list is empty
  201. if(m_count == 0)
  202. return;
  203. // If List element is only one
  204. // just simply call RemoveHead()
  205. if(m_count == 1)
  206. {
  207. RemoveHead();
  208. return;
  209. }
  210. // Save the current Tail
  211. // to a new node
  212. DoublyNode<T> * node = Tail;
  213. // Point the Tail Pointer
  214. // to the element before the current Tail
  215. Tail = Tail->Previous;
  216. // Set the new Next pointer of the new Tail
  217. // to NULL since we are going to delete
  218. // the last element
  219. Tail->Next = NULL;
  220. // Now it's safe to remove
  221. // the last element
  222. delete node;
  223. // One element is removed
  224. m_count--;
  225. }
  226. template <typename T>
  227. void DoublyLinkedList<T>::Remove(int index)
  228. {
  229. // Do nothing if list is empty
  230. if(m_count == 0)
  231. return;
  232. // Do nothing if index is out of bound
  233. if(index < 0 || index >= m_count)
  234. return;
  235. // If removing the current Head
  236. if(index == 0)
  237. {
  238. RemoveHead();
  239. return;
  240. }
  241. // If removing the current Tail
  242. else if(index == m_count - 1)
  243. {
  244. RemoveTail();
  245. return;
  246. }
  247. // Start to traverse the list
  248. // from the Head
  249. DoublyNode<T> * prevNode = Head;
  250. // Find the element before
  251. // the selected index
  252. for(int i = 0; i < index - 1; ++i)
  253. {
  254. prevNode = prevNode->Next;
  255. }
  256. // The removed element is after
  257. // the prevNode
  258. DoublyNode<T> * node = prevNode->Next;
  259. // The nextNode will be the neighbor of
  260. // prevNode if the node is removed
  261. DoublyNode<T> * nextNode = node->Next;
  262. // Link the prevNode to nextNode
  263. prevNode->Next = nextNode;
  264. nextNode->Previous = prevNode;
  265. // It's now safe to remove
  266. // the selected index element
  267. delete node;
  268. // One element is removed
  269. m_count--;
  270. }
  271. template <typename T>
  272. int DoublyLinkedList<T>::Count()
  273. {
  274. return m_count;
  275. }
  276. template <typename T>
  277. void DoublyLinkedList<T>::PrintList()
  278. {
  279. DoublyNode<T> * node = Head;
  280. while(node != NULL)
  281. {
  282. std::cout << node->Value << " -> ";
  283. node = node->Next;
  284. }
  285. std::cout << "NULL" << std::endl;
  286. }
  287. template <typename T>
  288. void DoublyLinkedList<T>::PrintListBackward()
  289. {
  290. DoublyNode<T> * node = Tail;
  291. while(node != NULL)
  292. {
  293. std::cout << node->Value << " -> ";
  294. node = node->Previous;
  295. }
  296. std::cout << "NULL" << std::endl;
  297. }
  298. #endif // DOUBLYLINKEDLIST_H