LinkedList.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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. int _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 int 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. }
  95. root->prev = node;
  96. node->next = root;
  97. node->prev = NULL;
  98. root = node;
  99. }
  100. // Initialize LinkedList with false values
  101. template<typename T>
  102. LinkedList<T>::LinkedList()
  103. {
  104. root=NULL;
  105. last=NULL;
  106. _size=0;
  107. }
  108. // Clear Nodes and free Memory
  109. template<typename T>
  110. LinkedList<T>::~LinkedList()
  111. {
  112. ListNode<T>* tmp;
  113. while(root!=NULL)
  114. {
  115. tmp=root;
  116. root=root->next;
  117. delete tmp;
  118. }
  119. last = NULL;
  120. _size=0;
  121. }
  122. /*
  123. Actualy "logic" coding
  124. */
  125. template<typename T>
  126. ListNode<T>* LinkedList<T>::getNode(int index){
  127. int _pos = 0;
  128. ListNode<T>* current = root;
  129. while(_pos < index && current){
  130. current = current->next;
  131. _pos++;
  132. }
  133. return false;
  134. }
  135. template<typename T>
  136. int LinkedList<T>::size() const{
  137. return _size;
  138. }
  139. template<typename T>
  140. bool LinkedList<T>::add(int index, T _t){
  141. if(index >= _size)
  142. return add(_t);
  143. if(index == 0)
  144. return unshift(_t);
  145. ListNode<T> *tmp = new ListNode<T>(),
  146. *_prev = getNode(index-1);
  147. tmp->data = _t;
  148. tmp->next = _prev->next;
  149. _prev->next = tmp;
  150. _size++;
  151. return true;
  152. }
  153. template<typename T>
  154. bool LinkedList<T>::add(T _t){
  155. ListNode<T> *tmp = new ListNode<T>();
  156. tmp->data = _t;
  157. tmp->next = NULL;
  158. if(root){
  159. // Already have elements inserted
  160. last->next = tmp;
  161. last = tmp;
  162. }else{
  163. // First element being inserted
  164. root = tmp;
  165. last = tmp;
  166. }
  167. _size++;
  168. return true;
  169. }
  170. template<typename T>
  171. bool LinkedList<T>::unshift(T _t){
  172. if(_size == 0)
  173. return add(_t);
  174. ListNode<T> *tmp = new ListNode<T>();
  175. tmp->next = root;
  176. tmp->data = _t;
  177. root = tmp;
  178. _size++;
  179. return true;
  180. }
  181. template<typename T>
  182. bool LinkedList<T>::set(int index, T _t){
  183. // Check if index position is in bounds
  184. if(index < 0 || index >= _size)
  185. return false;
  186. getNode(index)->data = _t;
  187. return true;
  188. }
  189. template<typename T>
  190. T LinkedList<T>::pop(){
  191. if(_size <= 0)
  192. return T();
  193. if(_size >= 2){
  194. ListNode<T> *tmp = getNode(_size - 2);
  195. T ret = tmp->next->data;
  196. delete(tmp->next);
  197. tmp->next = NULL;
  198. last = tmp;
  199. _size--;
  200. return ret;
  201. }else{
  202. // Only one element left on the list
  203. T ret = root->data;
  204. delete(root);
  205. root = NULL;
  206. last = NULL;
  207. _size = 0;
  208. return ret;
  209. }
  210. }
  211. template<typename T>
  212. T LinkedList<T>::shift(){
  213. if(_size <= 0)
  214. return T();
  215. if(_size > 1){
  216. ListNode<T> *_next = root->next;
  217. T ret = root->data;
  218. delete(root);
  219. root = _next;
  220. _size --;
  221. return ret;
  222. }else{
  223. // Only one left, then pop()
  224. return pop();
  225. }
  226. }
  227. template<typename T>
  228. T LinkedList<T>::remove(int index){
  229. if (index < 0 || index >= _size)
  230. {
  231. return T();
  232. }
  233. if(index == 0)
  234. return shift();
  235. if (index == _size-1)
  236. {
  237. return pop();
  238. }
  239. ListNode<T> *tmp = getNode(index - 1);
  240. ListNode<T> *toDelete = tmp->next;
  241. T ret = toDelete->data;
  242. tmp->next = tmp->next->next;
  243. delete(toDelete);
  244. _size--;
  245. return ret;
  246. }
  247. template<typename T>
  248. T LinkedList<T>::get(int index){
  249. ListNode<T> *tmp = getNode(index);
  250. return (tmp ? tmp->data : T());
  251. }
  252. template<typename T>
  253. void LinkedList<T>::clear(){
  254. while(size() > 0)
  255. shift();
  256. }
  257. #endif