LinkedList.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. virtual void remove(ListNode<T>* node);
  63. /*
  64. Remove last object;
  65. */
  66. virtual T pop();
  67. /*
  68. Remove first object;
  69. */
  70. virtual T shift();
  71. /*
  72. Get the index'th element on the list;
  73. Return Element if accessible,
  74. else, return false;
  75. */
  76. virtual T get(int index);
  77. /*
  78. Clear the entire array
  79. */
  80. virtual void clear();
  81. ListNode<T>* getNode(int index);
  82. virtual void spliceToFront(ListNode<T>* node);
  83. ListNode<T>* getHead() { return root; }
  84. T getLast() const { return last == NULL ? T() : last->data; }
  85. };
  86. template<typename T>
  87. void LinkedList<T>::spliceToFront(ListNode<T>* node) {
  88. // Node is already root
  89. if (node->prev == NULL) {
  90. return;
  91. }
  92. node->prev->next = node->next;
  93. if (node->next != NULL) {
  94. node->next->prev = node->prev;
  95. } else {
  96. last = node->prev;
  97. }
  98. root->prev = node;
  99. node->next = root;
  100. node->prev = NULL;
  101. root = node;
  102. }
  103. // Initialize LinkedList with false values
  104. template<typename T>
  105. LinkedList<T>::LinkedList()
  106. {
  107. root=NULL;
  108. last=NULL;
  109. _size=0;
  110. }
  111. // Clear Nodes and free Memory
  112. template<typename T>
  113. LinkedList<T>::~LinkedList()
  114. {
  115. ListNode<T>* tmp;
  116. while(root!=NULL)
  117. {
  118. tmp=root;
  119. root=root->next;
  120. delete tmp;
  121. }
  122. last = NULL;
  123. _size=0;
  124. }
  125. /*
  126. Actualy "logic" coding
  127. */
  128. template<typename T>
  129. ListNode<T>* LinkedList<T>::getNode(int index){
  130. int _pos = 0;
  131. ListNode<T>* current = root;
  132. while(_pos < index && current){
  133. current = current->next;
  134. _pos++;
  135. }
  136. return false;
  137. }
  138. template<typename T>
  139. size_t LinkedList<T>::size() const{
  140. return _size;
  141. }
  142. template<typename T>
  143. bool LinkedList<T>::add(int index, T _t){
  144. if(index >= _size)
  145. return add(_t);
  146. if(index == 0)
  147. return unshift(_t);
  148. ListNode<T> *tmp = new ListNode<T>(),
  149. *_prev = getNode(index-1);
  150. tmp->data = _t;
  151. tmp->next = _prev->next;
  152. _prev->next = tmp;
  153. _size++;
  154. return true;
  155. }
  156. template<typename T>
  157. bool LinkedList<T>::add(T _t){
  158. ListNode<T> *tmp = new ListNode<T>();
  159. tmp->data = _t;
  160. tmp->next = NULL;
  161. if(root){
  162. // Already have elements inserted
  163. last->next = tmp;
  164. tmp->prev = last;
  165. last = tmp;
  166. }else{
  167. // First element being inserted
  168. root = tmp;
  169. last = tmp;
  170. }
  171. _size++;
  172. return true;
  173. }
  174. template<typename T>
  175. bool LinkedList<T>::unshift(T _t){
  176. if(_size == 0)
  177. return add(_t);
  178. ListNode<T> *tmp = new ListNode<T>();
  179. tmp->next = root;
  180. root->prev = tmp;
  181. tmp->data = _t;
  182. root = tmp;
  183. _size++;
  184. return true;
  185. }
  186. template<typename T>
  187. bool LinkedList<T>::set(int index, T _t){
  188. // Check if index position is in bounds
  189. if(index < 0 || index >= _size)
  190. return false;
  191. getNode(index)->data = _t;
  192. return true;
  193. }
  194. template<typename T>
  195. T LinkedList<T>::pop(){
  196. if(_size <= 0)
  197. return T();
  198. if(_size >= 2){
  199. ListNode<T> *tmp = last->prev;
  200. T ret = tmp->next->data;
  201. delete(tmp->next);
  202. tmp->next = NULL;
  203. last = tmp;
  204. _size--;
  205. return ret;
  206. }else{
  207. // Only one element left on the list
  208. T ret = root->data;
  209. delete(root);
  210. root = NULL;
  211. last = NULL;
  212. _size = 0;
  213. return ret;
  214. }
  215. }
  216. template<typename T>
  217. T LinkedList<T>::shift(){
  218. if(_size <= 0)
  219. return T();
  220. if(_size > 1){
  221. ListNode<T> *_next = root->next;
  222. T ret = root->data;
  223. delete(root);
  224. root = _next;
  225. _size --;
  226. return ret;
  227. }else{
  228. // Only one left, then pop()
  229. return pop();
  230. }
  231. }
  232. template<typename T>
  233. void LinkedList<T>::remove(ListNode<T>* node){
  234. if (node == root) {
  235. shift();
  236. } else if (node == last) {
  237. pop();
  238. } else {
  239. ListNode<T>* prev = node->prev;
  240. ListNode<T>* next = node->next;
  241. prev->next = next;
  242. next->prev = prev;
  243. delete node;
  244. --_size;
  245. }
  246. }
  247. template<typename T>
  248. T LinkedList<T>::remove(int index){
  249. if (index < 0 || index >= _size)
  250. {
  251. return T();
  252. }
  253. if(index == 0)
  254. return shift();
  255. if (index == _size-1)
  256. {
  257. return pop();
  258. }
  259. ListNode<T> *tmp = getNode(index - 1);
  260. ListNode<T> *toDelete = tmp->next;
  261. T ret = toDelete->data;
  262. tmp->next = tmp->next->next;
  263. delete(toDelete);
  264. _size--;
  265. return ret;
  266. }
  267. template<typename T>
  268. T LinkedList<T>::get(int index){
  269. ListNode<T> *tmp = getNode(index);
  270. return (tmp ? tmp->data : T());
  271. }
  272. template<typename T>
  273. void LinkedList<T>::clear(){
  274. while(size() > 0)
  275. shift();
  276. }
  277. #endif