mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-06-06 02:36:49 +08: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
|