LinkedList.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. ********* Adapted from: *********
  3. https://github.com/ivanseidel/LinkedList
  4. Created by Ivan Seidel Gomes, March, 2013.
  5. Released into the public domain.
  6. *********************************
  7. Changes:
  8. - public access to ListNode (allows for splicing for LRU)
  9. - doubly-linked
  10. - remove caching stuff in favor of standard linked list iterating
  11. - remove sorting
  12. */
  13. #ifndef LinkedList_h
  14. #define LinkedList_h
  15. #include <stddef.h>
  16. template<class T>
  17. struct ListNode {
  18. T data;
  19. ListNode<T> *next;
  20. ListNode<T> *prev;
  21. };
  22. template <typename T>
  23. class LinkedList {
  24. protected:
  25. size_t _size;
  26. ListNode<T> *root;
  27. ListNode<T> *last;
  28. public:
  29. LinkedList();
  30. ~LinkedList();
  31. /*
  32. Returns current size of LinkedList
  33. */
  34. virtual size_t size() const;
  35. /*
  36. Adds a T object in the specified index;
  37. Unlink and link the LinkedList correcly;
  38. Increment _size
  39. */
  40. virtual bool add(int index, T);
  41. /*
  42. Adds a T object in the end of the LinkedList;
  43. Increment _size;
  44. */
  45. virtual bool add(T);
  46. /*
  47. Adds a T object in the start of the LinkedList;
  48. Increment _size;
  49. */
  50. virtual bool unshift(T);
  51. /*
  52. Set the object at index, with T;
  53. Increment _size;
  54. */
  55. virtual bool set(int index, T);
  56. /*
  57. Remove object at index;
  58. If index is not reachable, returns false;
  59. else, decrement _size
  60. */
  61. virtual T remove(int index);
  62. /*
  63. Remove last object;
  64. */
  65. virtual T pop();
  66. /*
  67. Remove first object;
  68. */
  69. virtual T shift();
  70. /*
  71. Get the index'th element on the list;
  72. Return Element if accessible,
  73. else, return false;
  74. */
  75. virtual T get(int index);
  76. /*
  77. Clear the entire array
  78. */
  79. virtual void clear();
  80. ListNode<T>* getNode(int index);
  81. virtual void spliceToFront(ListNode<T>* node);
  82. ListNode<T>* getHead() { return root; }
  83. T getLast() const { return last == NULL ? T() : last->data; }
  84. };
  85. template<typename T>
  86. void LinkedList<T>::spliceToFront(ListNode<T>* node) {
  87. // Node is already root
  88. if (node->prev == NULL) {
  89. return;
  90. }
  91. node->prev->next = node->next;
  92. if (node->next != NULL) {
  93. node->next->prev = node->prev;
  94. } else {
  95. last = node->prev;
  96. }
  97. root->prev = node;
  98. node->next = root;
  99. node->prev = NULL;
  100. root = node;
  101. }
  102. // Initialize LinkedList with false values
  103. template<typename T>
  104. LinkedList<T>::LinkedList()
  105. {
  106. root=NULL;
  107. last=NULL;
  108. _size=0;
  109. }
  110. // Clear Nodes and free Memory
  111. template<typename T>
  112. LinkedList<T>::~LinkedList()
  113. {
  114. ListNode<T>* tmp;
  115. while(root!=NULL)
  116. {
  117. tmp=root;
  118. root=root->next;
  119. delete tmp;
  120. }
  121. last = NULL;
  122. _size=0;
  123. }
  124. /*
  125. Actualy "logic" coding
  126. */
  127. template<typename T>
  128. ListNode<T>* LinkedList<T>::getNode(int index){
  129. int _pos = 0;
  130. ListNode<T>* current = root;
  131. while(_pos < index && current){
  132. current = current->next;
  133. _pos++;
  134. }
  135. return false;
  136. }
  137. template<typename T>
  138. size_t LinkedList<T>::size() const{
  139. return _size;
  140. }
  141. template<typename T>
  142. bool LinkedList<T>::add(int index, T _t){
  143. if(index >= _size)
  144. return add(_t);
  145. if(index == 0)
  146. return unshift(_t);
  147. ListNode<T> *tmp = new ListNode<T>(),
  148. *_prev = getNode(index-1);
  149. tmp->data = _t;
  150. tmp->next = _prev->next;
  151. _prev->next = tmp;
  152. _size++;
  153. return true;
  154. }
  155. template<typename T>
  156. bool LinkedList<T>::add(T _t){
  157. ListNode<T> *tmp = new ListNode<T>();
  158. tmp->data = _t;
  159. tmp->next = NULL;
  160. if(root){
  161. // Already have elements inserted
  162. last->next = tmp;
  163. last = tmp;
  164. }else{
  165. // First element being inserted
  166. root = tmp;
  167. last = tmp;
  168. }
  169. _size++;
  170. return true;
  171. }
  172. template<typename T>
  173. bool LinkedList<T>::unshift(T _t){
  174. if(_size == 0)
  175. return add(_t);
  176. ListNode<T> *tmp = new ListNode<T>();
  177. tmp->next = root;
  178. root->prev = tmp;
  179. tmp->data = _t;
  180. root = tmp;
  181. _size++;
  182. return true;
  183. }
  184. template<typename T>
  185. bool LinkedList<T>::set(int index, T _t){
  186. // Check if index position is in bounds
  187. if(index < 0 || index >= _size)
  188. return false;
  189. getNode(index)->data = _t;
  190. return true;
  191. }
  192. template<typename T>
  193. T LinkedList<T>::pop(){
  194. if(_size <= 0)
  195. return T();
  196. if(_size >= 2){
  197. ListNode<T> *tmp = last->prev;
  198. T ret = tmp->next->data;
  199. delete(tmp->next);
  200. tmp->next = NULL;
  201. last = tmp;
  202. _size--;
  203. return ret;
  204. }else{
  205. // Only one element left on the list
  206. T ret = root->data;
  207. delete(root);
  208. root = NULL;
  209. last = NULL;
  210. _size = 0;
  211. return ret;
  212. }
  213. }
  214. template<typename T>
  215. T LinkedList<T>::shift(){
  216. if(_size <= 0)
  217. return T();
  218. if(_size > 1){
  219. ListNode<T> *_next = root->next;
  220. T ret = root->data;
  221. delete(root);
  222. root = _next;
  223. _size --;
  224. return ret;
  225. }else{
  226. // Only one left, then pop()
  227. return pop();
  228. }
  229. }
  230. template<typename T>
  231. T LinkedList<T>::remove(int index){
  232. if (index < 0 || index >= _size)
  233. {
  234. return T();
  235. }
  236. if(index == 0)
  237. return shift();
  238. if (index == _size-1)
  239. {
  240. return pop();
  241. }
  242. ListNode<T> *tmp = getNode(index - 1);
  243. ListNode<T> *toDelete = tmp->next;
  244. T ret = toDelete->data;
  245. tmp->next = tmp->next->next;
  246. delete(toDelete);
  247. _size--;
  248. return ret;
  249. }
  250. template<typename T>
  251. T LinkedList<T>::get(int index){
  252. ListNode<T> *tmp = getNode(index);
  253. return (tmp ? tmp->data : T());
  254. }
  255. template<typename T>
  256. void LinkedList<T>::clear(){
  257. while(size() > 0)
  258. shift();
  259. }
  260. #endif