esp32_ethernet_milight_hub/lib/DataStructures/LinkedList.h
2021-01-15 22:49:01 +01:00

336 lines
5.6 KiB
C++

/*
********* 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:
size_t _size;
ListNode<T> *root;
ListNode<T> *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<T>* 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<T>* getNode(int index);
virtual void spliceToFront(ListNode<T>* node);
ListNode<T>* getHead() { return root; }
T getLast() const { return last == NULL ? T() : last->data; }
};
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;
} else {
last = 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>
size_t LinkedList<T>::size() const{
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;
tmp->prev = last;
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;
root->prev = tmp;
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 = 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<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>
void LinkedList<T>::remove(ListNode<T>* node){
if (node == root) {
shift();
} else if (node == last) {
pop();
} else {
ListNode<T>* prev = node->prev;
ListNode<T>* next = node->next;
prev->next = next;
next->prev = prev;
delete node;
--_size;
}
}
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