/* ********* 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 template struct ListNode { T data; ListNode *next; ListNode *prev; }; template class LinkedList { protected: size_t _size; ListNode *root; ListNode *last; public: LinkedList(); ~LinkedList(); /* Returns current size of LinkedList */ virtual size_t size() const; /* 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); virtual void remove(ListNode* node); /* 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* getNode(int index); virtual void spliceToFront(ListNode* node); ListNode* getHead() { return root; } T getLast() const { return last == NULL ? T() : last->data; } }; template void LinkedList::spliceToFront(ListNode* node) { // Node is already root if (node->prev == NULL) { return; } node->prev->next = node->next; if (node->next != NULL) { node->next->prev = node->prev; } else { last = node->prev; } root->prev = node; node->next = root; node->prev = NULL; root = node; } // Initialize LinkedList with false values template LinkedList::LinkedList() { root=NULL; last=NULL; _size=0; } // Clear Nodes and free Memory template LinkedList::~LinkedList() { ListNode* tmp; while(root!=NULL) { tmp=root; root=root->next; delete tmp; } last = NULL; _size=0; } /* Actualy "logic" coding */ template ListNode* LinkedList::getNode(int index){ int _pos = 0; ListNode* current = root; while(_pos < index && current){ current = current->next; _pos++; } return false; } template size_t LinkedList::size() const{ return _size; } template bool LinkedList::add(int index, T _t){ if(index >= _size) return add(_t); if(index == 0) return unshift(_t); ListNode *tmp = new ListNode(), *_prev = getNode(index-1); tmp->data = _t; tmp->next = _prev->next; _prev->next = tmp; _size++; return true; } template bool LinkedList::add(T _t){ ListNode *tmp = new ListNode(); tmp->data = _t; tmp->next = NULL; if(root){ // Already have elements inserted last->next = tmp; tmp->prev = last; last = tmp; }else{ // First element being inserted root = tmp; last = tmp; } _size++; return true; } template bool LinkedList::unshift(T _t){ if(_size == 0) return add(_t); ListNode *tmp = new ListNode(); tmp->next = root; root->prev = tmp; tmp->data = _t; root = tmp; _size++; return true; } template bool LinkedList::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 T LinkedList::pop(){ if(_size <= 0) return T(); if(_size >= 2){ ListNode *tmp = last->prev; 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 T LinkedList::shift(){ if(_size <= 0) return T(); if(_size > 1){ ListNode *_next = root->next; T ret = root->data; delete(root); root = _next; _size --; return ret; }else{ // Only one left, then pop() return pop(); } } template void LinkedList::remove(ListNode* node){ if (node == root) { shift(); } else if (node == last) { pop(); } else { ListNode* prev = node->prev; ListNode* next = node->next; prev->next = next; next->prev = prev; delete node; --_size; } } template T LinkedList::remove(int index){ if (index < 0 || index >= _size) { return T(); } if(index == 0) return shift(); if (index == _size-1) { return pop(); } ListNode *tmp = getNode(index - 1); ListNode *toDelete = tmp->next; T ret = toDelete->data; tmp->next = tmp->next->next; delete(toDelete); _size--; return ret; } template T LinkedList::get(int index){ ListNode *tmp = getNode(index); return (tmp ? tmp->data : T()); } template void LinkedList::clear(){ while(size() > 0) shift(); } #endif