Arduino List Library  3.0.1
The Ultimate Collection of Lists
DoubleLinkedList.hpp
Go to the documentation of this file.
1 
26 #ifndef LIST_DOUBLE_LINKED_LIST_HPP
27 #define LIST_DOUBLE_LINKED_LIST_HPP
28 
29 #include "AbstractList.hpp"
30 
36 template<typename T>
37 class DoubleLinkedList : public AbstractList<T> {
41  class Entry : public AbstractList<T>::AbstractEntry {
42  Entry *prev = nullptr;
43  Entry *next = nullptr;
44 
45  public:
49  ~Entry() {
50  next = nullptr;
51  prev = nullptr;
52  }
53 
59  Entry *getNext() const { return next; }
60 
66  void setNext(Entry *nextEntry) { next = nextEntry; }
67 
73  Entry *getPrev() const { return prev; }
74 
80  void setPrev(Entry *prevEntry) { prev = prevEntry; }
81  };
82 
83  Entry *head = nullptr;
84  Entry *tail = nullptr;
85 
86  protected:
90  T *getPointer(int index) override {
91  if (this->isIndexOutOfBounds(index)) {
92  return nullptr;
93  }
94 
95  Entry *current;
96  // optimize searching in large lists
97  if (index > abs(this->getSize() / 2)) {
98  current = tail;
99  for (int i = this->getSize(); i > index + 1; --i) {
100  current = current->getPrev();
101  }
102  } else {
103  current = head;
104  for (int i = 0; i < index; i++) {
105  current = current->getNext();
106  }
107  }
108 
109  return current->getValue(this->isMutable());
110  }
111 
112  public:
119  explicit DoubleLinkedList<T>(bool mutableList = false)
120  : AbstractList<T>(mutableList) {}
121 
125  ~DoubleLinkedList() { this->clear(); }
126 
128 
134  void addAtIndex(int index, T &value) override {
135  // it is allowed, that index == this->getSize() to insert it behind the last
136  // entry
137  if (extendedIsIndexOutOfBounds(index)) {
138  return;
139  }
140 
141  Entry *entry = new Entry();
142  entry->setValue(value, this->isMutable());
143 
144  if (index == 0) {
145  if (this->getSize() == 0) {
146  // Add entry to an empty list
147  tail = entry;
148  } else {
149  // Add entry to not empty list
150  entry->setNext(head);
151  head->setPrev(entry);
152  }
153  head = entry;
154  } else if (index == this->getSize()) {
155  // Add entry at not empty list but at last position
156  tail->setNext(entry);
157  entry->setPrev(tail);
158  tail = entry;
159  } else {
160  // Add entry to a not empty list, somewhere in the middle
161  Entry *current;
162 
163  // optimize searching in large lists
164  if (index >= abs(this->getSize() / 2)) {
165  current = tail;
166  for (int i = this->getSize(); i > index + 1; --i) {
167  current = current->getPrev();
168  }
169  entry->setNext(current);
170  entry->setPrev(current->getPrev());
171  entry->getPrev()->setNext(entry);
172  current->setPrev(entry);
173  } else {
174  current = head;
175  for (int i = 0; i < index - 1; ++i) {
176  current = current->getNext();
177  }
178  entry->setNext(current->getNext());
179  entry->setPrev(current);
180  entry->getNext()->setPrev(entry);
181  current->setNext(entry);
182  }
183  }
184 
185  this->increaseSize();
186  };
187 
191  void clear() override {
192  if (this->getSize() == 0) {
193  return;
194  }
195 
196  Entry *current = head;
197  Entry *next;
198  for (int i = 0; i < this->getSize(); ++i) {
199  next = current->getNext();
200 
201  delete current;
202  current = next;
203  }
204 
205  this->resetSize();
206  head = nullptr;
207  tail = nullptr;
208  }
209 
213  void remove(int index) override {
214  if (this->isIndexOutOfBounds(index)) {
215  return;
216  }
217 
218  Entry *current = head;
219 
220  // optimize searching in large lists
221  if (index >= abs(this->getSize() / 2)) {
222  if (index != 0) {
223  current = tail;
224  int i = this->getSize() - 1;
225  while (i > index - 1) {
226  current = current->getPrev();
227  --i;
228  }
229  }
230  } else {
231  if (index != 0) {
232  int i = 0;
233  while (i < index - 1) {
234  current = current->getNext();
235  i++;
236  }
237  }
238  }
239 
240  if (index == this->getSize() - 1) {
241  tail = current;
242  }
243 
244  if (index == 0) {
245  head = current->getNext();
246  }
247 
248  Entry *toDelete;
249  if (index == 0) {
250  toDelete = current;
251  head = current->getNext();
252  } else {
253  toDelete = current->getNext();
254  current->setNext(current->getNext()->getNext());
255  if (current->getNext() != nullptr) {
256  current->getNext()->setPrev(current);
257  }
258  }
259 
260  delete toDelete;
261 
262  this->decreaseSize();
263 
264  if (this->getSize() == 0) {
265  head = nullptr;
266  tail = nullptr;
267  }
268  }
269 };
270 
271 #endif// LIST_DOUBLE_LINKED_LIST_HPP
void resetSize()
Reset the size to zero.
Definition: AbstractList.hpp:120
int getSize() const
Get the number how many elements are saved in the list.
Definition: AbstractList.hpp:334
void addAtIndex(int index, T &value) override
Add the value to the list at the given index. The original entry at this index, and followings...
Definition: DoubleLinkedList.hpp:134
#define extendedIsIndexOutOfBounds(index)
Is the list mutable or immutable.
Definition: AbstractList.hpp:44
bool isIndexOutOfBounds(const int index) const
Method to verify if the given index is out of the range of the list size.
Definition: AbstractList.hpp:130
void increaseSize()
Increase the size of the list by one. Should only be called after an insertion!
Definition: AbstractList.hpp:109
~DoubleLinkedList()
Destructor of a DoubleLinkedList Object.
Definition: DoubleLinkedList.hpp:125
T * getPointer(int index) override
The last entry of the list.
Definition: DoubleLinkedList.hpp:90
Definition: AbstractList.hpp:50
void decreaseSize()
Decrease the size of the list by one. Should only be called after an deletion!
Definition: AbstractList.hpp:115
Implementation of a double-linked list.
Definition: DoubleLinkedList.hpp:37
bool isMutable() const
Check if the list is mutable.
Definition: AbstractList.hpp:341
void clear() override
Remove all elements from the List.
Definition: DoubleLinkedList.hpp:191
Abstract class from which all lists can be derived.
Definition: AbstractList.hpp:37