mirror of
				https://github.com/luc-github/ESP3D.git
				synced 2025-10-24 11:50:52 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			341 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			341 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
| 	GenLinkedList.h - V1.1 - Generic LinkedList implementation
 | |
| 	Works better with FIFO, because LIFO will need to
 | |
| 	search the entire List to find the last one;
 | |
| 
 | |
| 	For instructions, go to https://github.com/ivanseidel/LinkedList
 | |
| 
 | |
| 	Created by Ivan Seidel Gomes, March, 2013.
 | |
| 	Released into the public domain.
 | |
| 	Changelog: 2015/10/05: [Luc] Change false to NULL for pointers
 | |
| */
 | |
| 
 | |
| 
 | |
| #ifndef GenLinkedList_h
 | |
| #define GenLinkedList_h
 | |
| 
 | |
| template<class T>
 | |
| struct ListNode {
 | |
|     T data;
 | |
|     ListNode<T> *next;
 | |
| };
 | |
| 
 | |
| template <typename T>
 | |
| class GenLinkedList
 | |
| {
 | |
| 
 | |
| protected:
 | |
|     int _size;
 | |
|     ListNode<T> *root;
 | |
|     ListNode<T>	*last;
 | |
| 
 | |
|     // Helps "get" method, by saving last position
 | |
|     ListNode<T> *lastNodeGot;
 | |
|     int lastIndexGot;
 | |
|     // isCached should be set to FALSE
 | |
|     // every time the list suffer changes
 | |
|     bool isCached;
 | |
| 
 | |
|     ListNode<T>* getNode (int index);
 | |
| 
 | |
| public:
 | |
|     GenLinkedList();
 | |
|     ~GenLinkedList();
 | |
| 
 | |
|     /*
 | |
|     	Returns current size of GenLinkedList
 | |
|     */
 | |
|     virtual int size();
 | |
|     /*
 | |
|     	Adds a T object in the specified index;
 | |
|     	Unlink and link the GenLinkedList correcly;
 | |
|     	Increment _size
 | |
|     */
 | |
|     virtual bool add (int index, T);
 | |
|     /*
 | |
|     	Adds a T object in the end of the GenLinkedList;
 | |
|     	Increment _size;
 | |
|     */
 | |
|     virtual bool add (T);
 | |
|     /*
 | |
|     	Adds a T object in the start of the GenLinkedList;
 | |
|     	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();
 | |
| 
 | |
| };
 | |
| 
 | |
| // Initialize GenLinkedList with false values
 | |
| template<typename T>
 | |
| GenLinkedList<T>::GenLinkedList()
 | |
| {
 | |
|     root = NULL;
 | |
|     last = NULL;
 | |
|     _size = 0;
 | |
| 
 | |
|     lastNodeGot = root;
 | |
|     lastIndexGot = 0;
 | |
|     isCached = false;
 | |
| }
 | |
| 
 | |
| // Clear Nodes and free Memory
 | |
| template<typename T>
 | |
| GenLinkedList<T>::~GenLinkedList()
 | |
| {
 | |
|     ListNode<T>* tmp;
 | |
|     while (root != NULL) {
 | |
|         tmp = root;
 | |
|         root = root->next;
 | |
|         delete tmp;
 | |
|     }
 | |
|     last = NULL;
 | |
|     _size = 0;
 | |
|     isCached = false;
 | |
| }
 | |
| 
 | |
| /*
 | |
| 	Actually "logic" coding
 | |
| */
 | |
| 
 | |
| template<typename T>
 | |
| ListNode<T>* GenLinkedList<T>::getNode (int index)
 | |
| {
 | |
| 
 | |
|     int _pos = 0;
 | |
|     ListNode<T>* current = root;
 | |
| 
 | |
|     // Check if the node trying to get is
 | |
|     // immediately AFTER the previous got one
 | |
|     if (isCached && lastIndexGot <= index) {
 | |
|         _pos = lastIndexGot;
 | |
|         current = lastNodeGot;
 | |
|     }
 | |
| 
 | |
|     while (_pos < index && current) {
 | |
|         current = current->next;
 | |
| 
 | |
|         _pos++;
 | |
|     }
 | |
| 
 | |
|     // Check if the object index got is the same as the required
 | |
|     if (_pos == index) {
 | |
|         isCached = true;
 | |
|         lastIndexGot = index;
 | |
|         lastNodeGot = current;
 | |
| 
 | |
|         return current;
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| template<typename T>
 | |
| int GenLinkedList<T>::size()
 | |
| {
 | |
|     return _size;
 | |
| }
 | |
| 
 | |
| template<typename T>
 | |
| bool GenLinkedList<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++;
 | |
|     isCached = false;
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| template<typename T>
 | |
| bool GenLinkedList<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++;
 | |
|     isCached = false;
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| template<typename T>
 | |
| bool GenLinkedList<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++;
 | |
|     isCached = false;
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| template<typename T>
 | |
| bool GenLinkedList<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 GenLinkedList<T>::pop()
 | |
| {
 | |
|     if (_size <= 0) {
 | |
|         return T();
 | |
|     }
 | |
| 
 | |
|     isCached = false;
 | |
| 
 | |
|     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 GenLinkedList<T>::shift()
 | |
| {
 | |
|     if (_size <= 0) {
 | |
|         return T();
 | |
|     }
 | |
| 
 | |
|     if (_size > 1) {
 | |
|         ListNode<T> *_next = root->next;
 | |
|         T ret = root->data;
 | |
|         delete (root);
 | |
|         root = _next;
 | |
|         _size --;
 | |
|         isCached = false;
 | |
| 
 | |
|         return ret;
 | |
|     } else {
 | |
|         // Only one left, then pop()
 | |
|         return pop();
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| template<typename T>
 | |
| T GenLinkedList<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--;
 | |
|     isCached = false;
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| template<typename T>
 | |
| T GenLinkedList<T>::get (int index)
 | |
| {
 | |
|     ListNode<T> *tmp = getNode (index);
 | |
| 
 | |
|     return (tmp ? tmp->data : T() );
 | |
| }
 | |
| 
 | |
| template<typename T>
 | |
| void GenLinkedList<T>::clear()
 | |
| {
 | |
|     while (size() > 0) {
 | |
|         shift();
 | |
|     }
 | |
| }
 | |
| 
 | |
| #endif
 |