Skip to content

Commit 9785e13

Browse files
authored
Merge pull request #11 from nkaaf/double_linked_list
DoubleLinkedList
2 parents 45290cc + 083269e commit 9785e13

File tree

3 files changed

+275
-7
lines changed

3 files changed

+275
-7
lines changed

keywords.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
AbstractList KEYWORD1
1010
List KEYWORD1
1111
SingleLinkedList KEYWORD1
12+
DoubleLinkedList KEYWORD1
1213

1314
###########################################
1415
# Methods and Functions (KEYWORD2)

src/DoubleLinkedList.hpp

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
/*!
2+
* @file SingleLinkedList.hpp
3+
*
4+
* This file is part of the List library. It extends the arduino ecosystem with
5+
* easy-to-use list implementations. They are specially designed and optimized
6+
* for different purposes.
7+
*
8+
* Copyright (C) 2022 Niklas Kaaf
9+
*
10+
* This library is free software; you can redistribute it and/or
11+
* modify it under the terms of the GNU Lesser General Public
12+
* License as published by the Free Software Foundation; either
13+
* version 2.1 of the License, or (at your option) any later version.
14+
*
15+
* This library is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18+
* Lesser General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU Lesser General Public
21+
* License along with this library; if not, write to the Free Software
22+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
23+
* USA
24+
*/
25+
26+
#ifndef LIST_DOUBLE_LINKED_LIST_HPP
27+
#define LIST_DOUBLE_LINKED_LIST_HPP
28+
29+
#include "AbstractList.hpp"
30+
31+
/*!
32+
* @brief Implementation of a double-linked list.
33+
*
34+
* @tparam T Data Type of entries, that should be stored in the list.
35+
*/
36+
template <typename T> class DoubleLinkedList : public AbstractList<T> {
37+
private:
38+
/*!
39+
* @brief Class representing one entry of the list.
40+
*/
41+
class Entry : public AbstractList<T>::AbstractEntry {
42+
private:
43+
Entry *prev = nullptr; /// Pointer to the previous element of the list.
44+
Entry *next = nullptr; /// Pointer to the next element of the list.
45+
46+
public:
47+
/*!
48+
* @brief Constructor of an Entry Object.
49+
*
50+
* @param value Value of the entry.
51+
*/
52+
explicit Entry(T *value) : AbstractList<T>::AbstractEntry(value) {}
53+
54+
/*!
55+
* @brief Get the next entry of the list.
56+
*
57+
* @return Pointer to the next element.
58+
*/
59+
Entry *getNext() const { return next; }
60+
61+
/*!
62+
* @brief Set the next entry of the list.
63+
*
64+
* @param nextEntry Pointer to the next entry.
65+
*/
66+
void setNext(Entry *nextEntry) { next = nextEntry; }
67+
68+
/*!
69+
* @brief Get the previous entry of the list.
70+
*
71+
* @return Pointer to the previous element.
72+
*/
73+
Entry *getPrev() const { return prev; }
74+
75+
/*!
76+
* @brief Set the previous entry fo the list.
77+
*
78+
* @param prevEntry Pointer to the previous entry.
79+
*/
80+
void setPrev(Entry *prevEntry) { prev = prevEntry; }
81+
};
82+
83+
Entry *head = nullptr; /// The first entry of the list.
84+
Entry *tail = nullptr; /// The last entry of the list.
85+
86+
protected:
87+
T *get(int index) override {
88+
if (this->isIndexOutOfBounds(index)) {
89+
return nullptr;
90+
}
91+
92+
Entry *current;
93+
// optimize searching in large lists
94+
if (index > abs(this->getSize() / 2)) {
95+
current = tail;
96+
for (int i = this->getSize(); i > index + 1; --i) {
97+
current = current->getPrev();
98+
}
99+
} else {
100+
current = head;
101+
for (int i = 0; i < index; i++) {
102+
current = current->getNext();
103+
}
104+
}
105+
106+
if (this->isMutable()) {
107+
return (T *)current->getValue();
108+
} else {
109+
T val = *current->getValue();
110+
T *finalValue;
111+
createFinalValue(val, finalValue, T);
112+
return finalValue;
113+
}
114+
}
115+
116+
public:
117+
/*!
118+
* @brief Constructor of a DoubleLinkedList Object.
119+
*
120+
* @param mutableList true if the list should be mutable; false otherwise
121+
* (default).
122+
*/
123+
explicit DoubleLinkedList<T>(bool mutableList = false)
124+
: AbstractList<T>(mutableList) {}
125+
126+
/*!
127+
* @brief Destructor of a DoubleLinkedList Object.
128+
*/
129+
~DoubleLinkedList() {
130+
if (head != nullptr) {
131+
Entry *current = head;
132+
Entry *next;
133+
for (int i = 0; i < this->getSize(); ++i) {
134+
next = current->getNext();
135+
136+
if (!this->isMutable()) {
137+
current->freeValue();
138+
}
139+
140+
delete current;
141+
current = next;
142+
}
143+
}
144+
}
145+
146+
void addAtIndex(int index, T &value) override {
147+
// it is allowed, that index == this->getSize() to insert it behind the last
148+
// entry
149+
if (extendedIsIndexOutOfBounds(index)) {
150+
return;
151+
}
152+
153+
Entry *entry;
154+
155+
if (this->isMutable()) {
156+
entry = new Entry(&value);
157+
} else {
158+
T *finalValue;
159+
createFinalValue(value, finalValue, T);
160+
entry = new Entry(finalValue);
161+
}
162+
163+
if (index == 0) {
164+
if (this->getSize() == 0) {
165+
// Add entry to an empty list
166+
tail = entry;
167+
} else {
168+
// Add entry to not empty list
169+
entry->setNext(head);
170+
head->setPrev(entry);
171+
}
172+
head = entry;
173+
} else if (index == this->getSize()) {
174+
// Add entry at not empty list but at last position
175+
tail->setNext(entry);
176+
entry->setPrev(tail);
177+
tail = entry;
178+
} else {
179+
// Add entry to a not empty list, somewhere in the middle
180+
Entry *current;
181+
182+
// optimize searching in large lists
183+
if (index >= abs(this->getSize() / 2)) {
184+
current = tail;
185+
for (int i = this->getSize(); i > index + 1; --i) {
186+
current = current->getPrev();
187+
}
188+
entry->setNext(current);
189+
entry->setPrev(current->getPrev());
190+
current->setPrev(entry);
191+
} else {
192+
current = head;
193+
for (int i = 0; i < index - 1; ++i) {
194+
current = current->getNext();
195+
}
196+
entry->setNext(current->getNext());
197+
entry->setPrev(current);
198+
entry->getNext()->setPrev(entry);
199+
current->setNext(entry);
200+
}
201+
}
202+
203+
this->increaseSize();
204+
};
205+
206+
void remove(int index) override {
207+
if (this->isIndexOutOfBounds(index)) {
208+
return;
209+
}
210+
211+
Entry *current = head;
212+
213+
// optimize searching in large lists
214+
if (index >= abs(this->getSize() / 2)) {
215+
if (index != 0) {
216+
current = tail;
217+
int i = this->getSize() - 1;
218+
while (i > index - 1) {
219+
current = current->getPrev();
220+
i--;
221+
}
222+
}
223+
} else {
224+
if (index != 0) {
225+
int i = 0;
226+
while (i < index - 1) {
227+
current = current->getNext();
228+
i++;
229+
}
230+
}
231+
}
232+
233+
if (index == this->getSize() - 1) {
234+
tail = current;
235+
}
236+
237+
if (index == 0) {
238+
head = current->getNext();
239+
}
240+
241+
Entry *toDelete;
242+
if (index == 0) {
243+
toDelete = current;
244+
head = current->getNext();
245+
} else {
246+
toDelete = current->getNext();
247+
current->setNext(current->getNext()->getNext());
248+
if (current->getNext() != nullptr) {
249+
current->getNext()->setPrev(current);
250+
}
251+
}
252+
253+
if (!this->isMutable()) {
254+
toDelete->freeValue();
255+
}
256+
delete toDelete;
257+
258+
this->decreaseSize();
259+
260+
if (this->getSize() == 0) {
261+
head = nullptr;
262+
tail = nullptr;
263+
}
264+
}
265+
};
266+
267+
#endif // LIST_DOUBLE_LINKED_LIST_HPP

src/SingleLinkedList.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -184,19 +184,19 @@ template <typename T> class SingleLinkedList : public AbstractList<T> {
184184
tail = current;
185185
}
186186

187+
Entry *toDelete;
187188
if (index == 0) {
189+
toDelete = current;
188190
head = current->getNext();
189-
}
190-
191-
// current is always the element to delete
192-
if (index != 0) {
193-
current = current->getNext();
191+
} else {
192+
toDelete = current->getNext();
193+
current->setNext(current->getNext()->getNext());
194194
}
195195

196196
if (!this->isMutable()) {
197-
current->freeValue();
197+
toDelete->freeValue();
198198
}
199-
delete current;
199+
delete toDelete;
200200

201201
this->decreaseSize();
202202

0 commit comments

Comments
 (0)