|
@@ -0,0 +1,313 @@
|
|
|
|
|
+/*
|
|
|
|
|
+ ********* Adapted from: *********
|
|
|
|
|
+ https://github.com/ivanseidel/LinkedList
|
|
|
|
|
+ Created by Ivan Seidel Gomes, March, 2013.
|
|
|
|
|
+ Released into the public domain.
|
|
|
|
|
+ *********************************
|
|
|
|
|
+
|
|
|
|
|
+ Changes:
|
|
|
|
|
+ - public access to ListNode (allows for splicing for LRU)
|
|
|
|
|
+ - doubly-linked
|
|
|
|
|
+ - remove caching stuff in favor of standard linked list iterating
|
|
|
|
|
+ - remove sorting
|
|
|
|
|
+*/
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+#ifndef LinkedList_h
|
|
|
|
|
+#define LinkedList_h
|
|
|
|
|
+
|
|
|
|
|
+#include <stddef.h>
|
|
|
|
|
+
|
|
|
|
|
+template<class T>
|
|
|
|
|
+struct ListNode {
|
|
|
|
|
+ T data;
|
|
|
|
|
+ ListNode<T> *next;
|
|
|
|
|
+ ListNode<T> *prev;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+template <typename T>
|
|
|
|
|
+class LinkedList {
|
|
|
|
|
+
|
|
|
|
|
+protected:
|
|
|
|
|
+ int _size;
|
|
|
|
|
+ ListNode<T> *root;
|
|
|
|
|
+ ListNode<T> *last;
|
|
|
|
|
+
|
|
|
|
|
+public:
|
|
|
|
|
+ LinkedList();
|
|
|
|
|
+ ~LinkedList();
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ Returns current size of LinkedList
|
|
|
|
|
+ */
|
|
|
|
|
+ virtual int size();
|
|
|
|
|
+ /*
|
|
|
|
|
+ Adds a T object in the specified index;
|
|
|
|
|
+ Unlink and link the LinkedList correcly;
|
|
|
|
|
+ Increment _size
|
|
|
|
|
+ */
|
|
|
|
|
+ virtual bool add(int index, T);
|
|
|
|
|
+ /*
|
|
|
|
|
+ Adds a T object in the end of the LinkedList;
|
|
|
|
|
+ Increment _size;
|
|
|
|
|
+ */
|
|
|
|
|
+ virtual bool add(T);
|
|
|
|
|
+ /*
|
|
|
|
|
+ Adds a T object in the start of the LinkedList;
|
|
|
|
|
+ Increment _size;
|
|
|
|
|
+ */
|
|
|
|
|
+ virtual bool unshift(T);
|
|
|
|
|
+ /*
|
|
|
|
|
+ Set the object at index, with T;
|
|
|
|
|
+ Increment _size;
|
|
|
|
|
+ */
|
|
|
|
|
+ virtual bool set(int index, T);
|
|
|
|
|
+ /*
|
|
|
|
|
+ Remove object at index;
|
|
|
|
|
+ If index is not reachable, returns false;
|
|
|
|
|
+ else, decrement _size
|
|
|
|
|
+ */
|
|
|
|
|
+ virtual T remove(int index);
|
|
|
|
|
+ /*
|
|
|
|
|
+ Remove last object;
|
|
|
|
|
+ */
|
|
|
|
|
+ virtual T pop();
|
|
|
|
|
+ /*
|
|
|
|
|
+ Remove first object;
|
|
|
|
|
+ */
|
|
|
|
|
+ virtual T shift();
|
|
|
|
|
+ /*
|
|
|
|
|
+ Get the index'th element on the list;
|
|
|
|
|
+ Return Element if accessible,
|
|
|
|
|
+ else, return false;
|
|
|
|
|
+ */
|
|
|
|
|
+ virtual T get(int index);
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ Clear the entire array
|
|
|
|
|
+ */
|
|
|
|
|
+ virtual void clear();
|
|
|
|
|
+
|
|
|
|
|
+ ListNode<T>* getNode(int index);
|
|
|
|
|
+ virtual void spliceToFront(ListNode<T>* node);
|
|
|
|
|
+ ListNode<T>* getHead() { return root; }
|
|
|
|
|
+
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+void LinkedList<T>::spliceToFront(ListNode<T>* node) {
|
|
|
|
|
+ // Node is already root
|
|
|
|
|
+ if (node->prev == NULL) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ node->prev->next = node->next;
|
|
|
|
|
+ if (node->next != NULL) {
|
|
|
|
|
+ node->next->prev = node->prev;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ root->prev = node;
|
|
|
|
|
+ node->next = root;
|
|
|
|
|
+ node->prev = NULL;
|
|
|
|
|
+ root = node;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Initialize LinkedList with false values
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+LinkedList<T>::LinkedList()
|
|
|
|
|
+{
|
|
|
|
|
+ root=NULL;
|
|
|
|
|
+ last=NULL;
|
|
|
|
|
+ _size=0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Clear Nodes and free Memory
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+LinkedList<T>::~LinkedList()
|
|
|
|
|
+{
|
|
|
|
|
+ ListNode<T>* tmp;
|
|
|
|
|
+ while(root!=NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ tmp=root;
|
|
|
|
|
+ root=root->next;
|
|
|
|
|
+ delete tmp;
|
|
|
|
|
+ }
|
|
|
|
|
+ last = NULL;
|
|
|
|
|
+ _size=0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ Actualy "logic" coding
|
|
|
|
|
+*/
|
|
|
|
|
+
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+ListNode<T>* LinkedList<T>::getNode(int index){
|
|
|
|
|
+
|
|
|
|
|
+ int _pos = 0;
|
|
|
|
|
+ ListNode<T>* current = root;
|
|
|
|
|
+
|
|
|
|
|
+ while(_pos < index && current){
|
|
|
|
|
+ current = current->next;
|
|
|
|
|
+
|
|
|
|
|
+ _pos++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return false;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+int LinkedList<T>::size(){
|
|
|
|
|
+ return _size;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+bool LinkedList<T>::add(int index, T _t){
|
|
|
|
|
+
|
|
|
|
|
+ if(index >= _size)
|
|
|
|
|
+ return add(_t);
|
|
|
|
|
+
|
|
|
|
|
+ if(index == 0)
|
|
|
|
|
+ return unshift(_t);
|
|
|
|
|
+
|
|
|
|
|
+ ListNode<T> *tmp = new ListNode<T>(),
|
|
|
|
|
+ *_prev = getNode(index-1);
|
|
|
|
|
+ tmp->data = _t;
|
|
|
|
|
+ tmp->next = _prev->next;
|
|
|
|
|
+ _prev->next = tmp;
|
|
|
|
|
+
|
|
|
|
|
+ _size++;
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+bool LinkedList<T>::add(T _t){
|
|
|
|
|
+
|
|
|
|
|
+ ListNode<T> *tmp = new ListNode<T>();
|
|
|
|
|
+ tmp->data = _t;
|
|
|
|
|
+ tmp->next = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ if(root){
|
|
|
|
|
+ // Already have elements inserted
|
|
|
|
|
+ last->next = tmp;
|
|
|
|
|
+ last = tmp;
|
|
|
|
|
+ }else{
|
|
|
|
|
+ // First element being inserted
|
|
|
|
|
+ root = tmp;
|
|
|
|
|
+ last = tmp;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ _size++;
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+bool LinkedList<T>::unshift(T _t){
|
|
|
|
|
+
|
|
|
|
|
+ if(_size == 0)
|
|
|
|
|
+ return add(_t);
|
|
|
|
|
+
|
|
|
|
|
+ ListNode<T> *tmp = new ListNode<T>();
|
|
|
|
|
+ tmp->next = root;
|
|
|
|
|
+ tmp->data = _t;
|
|
|
|
|
+ root = tmp;
|
|
|
|
|
+
|
|
|
|
|
+ _size++;
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+bool LinkedList<T>::set(int index, T _t){
|
|
|
|
|
+ // Check if index position is in bounds
|
|
|
|
|
+ if(index < 0 || index >= _size)
|
|
|
|
|
+ return false;
|
|
|
|
|
+
|
|
|
|
|
+ getNode(index)->data = _t;
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+T LinkedList<T>::pop(){
|
|
|
|
|
+ if(_size <= 0)
|
|
|
|
|
+ return T();
|
|
|
|
|
+
|
|
|
|
|
+ if(_size >= 2){
|
|
|
|
|
+ ListNode<T> *tmp = getNode(_size - 2);
|
|
|
|
|
+ T ret = tmp->next->data;
|
|
|
|
|
+ delete(tmp->next);
|
|
|
|
|
+ tmp->next = NULL;
|
|
|
|
|
+ last = tmp;
|
|
|
|
|
+ _size--;
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ }else{
|
|
|
|
|
+ // Only one element left on the list
|
|
|
|
|
+ T ret = root->data;
|
|
|
|
|
+ delete(root);
|
|
|
|
|
+ root = NULL;
|
|
|
|
|
+ last = NULL;
|
|
|
|
|
+ _size = 0;
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+T LinkedList<T>::shift(){
|
|
|
|
|
+ if(_size <= 0)
|
|
|
|
|
+ return T();
|
|
|
|
|
+
|
|
|
|
|
+ if(_size > 1){
|
|
|
|
|
+ ListNode<T> *_next = root->next;
|
|
|
|
|
+ T ret = root->data;
|
|
|
|
|
+ delete(root);
|
|
|
|
|
+ root = _next;
|
|
|
|
|
+ _size --;
|
|
|
|
|
+
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ }else{
|
|
|
|
|
+ // Only one left, then pop()
|
|
|
|
|
+ return pop();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+T LinkedList<T>::remove(int index){
|
|
|
|
|
+ if (index < 0 || index >= _size)
|
|
|
|
|
+ {
|
|
|
|
|
+ return T();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(index == 0)
|
|
|
|
|
+ return shift();
|
|
|
|
|
+
|
|
|
|
|
+ if (index == _size-1)
|
|
|
|
|
+ {
|
|
|
|
|
+ return pop();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ListNode<T> *tmp = getNode(index - 1);
|
|
|
|
|
+ ListNode<T> *toDelete = tmp->next;
|
|
|
|
|
+ T ret = toDelete->data;
|
|
|
|
|
+ tmp->next = tmp->next->next;
|
|
|
|
|
+ delete(toDelete);
|
|
|
|
|
+ _size--;
|
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+T LinkedList<T>::get(int index){
|
|
|
|
|
+ ListNode<T> *tmp = getNode(index);
|
|
|
|
|
+
|
|
|
|
|
+ return (tmp ? tmp->data : T());
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<typename T>
|
|
|
|
|
+void LinkedList<T>::clear(){
|
|
|
|
|
+ while(size() > 0)
|
|
|
|
|
+ shift();
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|