AlgoPlus v0.1.0
Loading...
Searching...
No Matches
doubly_linked_list.h
1#ifndef DOUBLY_LINKED_LIST_H
2#define DOUBLY_LINKED_LIST_H
3
4#ifdef ENABLE_LINKED_LIST_VISUALIZATION
5#include "../../visualization/list_visual/linked_list_visualization.h"
6#endif
7
8#ifdef __cplusplus
9#include <iostream>
10#include <memory>
11#include <string>
12#include <type_traits>
13#include <vector>
14#endif
15
19template <typename T> class doubly_linked_list {
20 public:
26 inline explicit doubly_linked_list(std::vector<T> _elements = {}) noexcept
27 : root(nullptr), tail(nullptr) {
28 if (!_elements.empty()) {
29 for (T& x : _elements) {
30 this->push_back(x);
31 }
32 }
33 }
34
39 inline explicit doubly_linked_list(const doubly_linked_list& l)
40 : root(l.root), tail(l.tail), _size(l._size) {}
41
48 root = l.root;
49 tail = l.tail;
50 _size = l._size;
51 return *this;
52 }
53
58 inline bool empty() { return root == nullptr; }
59
64 inline size_t size() { return _size; }
65
66 class Iterator;
67
73 inline Iterator begin() { return Iterator(root); }
74
80 inline Iterator end() { return Iterator(nullptr); }
81
87 inline bool search(T key);
88
93 inline void push_back(T key);
94
99 inline void push_front(T key);
100
105 inline void erase(T key);
106
111 inline std::vector<T> elements();
112
117 inline void reverse();
118
123 inline void visualize();
124
128 inline friend std::ostream& operator<<(std::ostream& out, doubly_linked_list<T>& l) {
129 out << '{';
130 std::shared_ptr<node> head = l.root;
131 while (head) {
132 out << head->val << ' ';
133 head = head->next;
134 }
135 out << '}' << '\n';
136 return out;
137 }
138
139 private:
146 struct node {
147 T val;
148 std::shared_ptr<node> next;
149 std::shared_ptr<node> prev;
150 node(T key = 0) : val(key), next(nullptr), prev(nullptr) {}
151 };
152 std::shared_ptr<node> root;
153 std::shared_ptr<node> tail;
154 size_t _size{0};
155
156 std::string generate();
157};
158
159template <typename T> bool doubly_linked_list<T>::search(T key) {
160 if (this->empty()) {
161 return false;
162 } else {
163 std::shared_ptr<node> t = root;
164 while (t != nullptr && t->val != key) {
165 t = t->next;
166 }
167 return (t == nullptr || t->val != key) ? false : true;
168 }
169 return false;
170}
171
172template <typename T> void doubly_linked_list<T>::push_back(T key) {
173 std::shared_ptr<node> p = std::make_shared<node>(key);
174 p->prev = tail;
175 p->next = nullptr;
176 if (tail != nullptr) {
177 tail->next = p;
178 }
179 if (root == nullptr) {
180 root = p;
181 }
182 tail = p;
183 _size++;
184}
185
186template <typename T> void doubly_linked_list<T>::push_front(T key) {
187 std::shared_ptr<node> p = std::make_shared<node>(key);
188 p->next = root;
189 p->prev = nullptr;
190 if (root != nullptr) {
191 root->prev = p;
192 }
193 if (tail == nullptr) {
194 tail = p;
195 }
196 root = p;
197 _size++;
198}
199
200template <typename T> void doubly_linked_list<T>::erase(T key) {
201 if (root == nullptr) {
202 return;
203 }
204 std::shared_ptr<node> head = root;
205 while (head && head->val != key) {
206 head = head->next;
207 }
208 if (head == nullptr) {
209 return;
210 }
211 if (head->next != nullptr) {
212 if (head == root) {
213 root = root->next;
214 }
215 head->next->prev = head->prev;
216 }
217 if (head->prev != nullptr) {
218 if (head == tail) {
219 tail = tail->prev;
220 }
221 head->prev->next = head->next;
222 }
223}
224
225template <typename T> std::vector<T> doubly_linked_list<T>::elements() {
226 std::vector<T> _elements;
227 if (this->empty()) {
228 return _elements;
229 }
230 std::shared_ptr<node> head = root;
231 while (head) {
232 _elements.push_back(head->val);
233 head = head->next;
234 }
235 return _elements;
236}
237
238template <typename T> void doubly_linked_list<T>::reverse() {
239 std::shared_ptr<node> current = root;
240 std::shared_ptr<node> temp{nullptr};
241
242 while (current != nullptr) {
243 temp = current->prev;
244 current->prev = current->next;
245 current->next = temp;
246 current = current->prev;
247 }
248
249 if (temp) {
250 root = temp->prev;
251 }
252}
253
254template <typename T> std::string doubly_linked_list<T>::generate() {
255 std::string gen;
256 gen += "rankdir=LR;";
257 gen += '\n';
258 gen += "node [shape=record;]";
259 gen += '\n';
260 std::vector<T> els = this->elements();
261 if (std::is_same_v<T, std::string> || std::is_same_v<T, char>) {
262 for (auto& x : els) {
263 gen += x;
264 gen += " [label=<{ ";
265 gen += x;
266 gen += " | }>] ;";
267 gen += '\n';
268 }
269
270 std::shared_ptr<node> curr = root;
271 while (curr->next) {
272 gen += curr->val;
273 gen += ":ref -> ";
274 gen += curr->next->val;
275 gen += ":data [arrowhead=vee, arrowtail=dot, dir=both];";
276 gen += '\n';
277
278 gen += curr->next->val;
279 gen += ":data -> ";
280 gen += curr->val;
281 gen += ":ref [arrowhead=vee, arrowtail=dot, dir=both];";
282 gen += '\n';
283
284 curr = curr->next;
285 }
286 } else {
287 for (auto& x : els) {
288 gen += std::to_string(x);
289 gen += " [label=<{ ";
290 gen += std::to_string(x);
291 gen += " | }>] ;";
292 gen += '\n';
293 }
294
295 std::shared_ptr<node> curr = root;
296 while (curr->next) {
297 gen += std::to_string(curr->val);
298 gen += ":ref -> ";
299 gen += std::to_string(curr->next->val);
300 gen += ":data [arrowhead=vee, arrowtail=dot, dir=both];";
301 gen += '\n';
302
303 gen += std::to_string(curr->next->val);
304 gen += ":data -> ";
305 gen += std::to_string(curr->val);
306 gen += ":ref [arrowhead=vee, arrowtail=dot, dir=both];";
307 gen += '\n';
308
309 curr = curr->next;
310 }
311 }
312 return gen;
313}
314
315#ifdef LINKED_LIST_VISUALIZATION_H
316template <typename T> void doubly_linked_list<T>::visualize() {
317 std::string generated = this->generate();
318 linked_list_visualization::visualize(generated);
319}
320#endif
321
325template <typename T> class doubly_linked_list<T>::Iterator {
326 private:
327 std::shared_ptr<node> curr_root;
328
329 public:
335 explicit Iterator(const std::shared_ptr<node>& l) noexcept : curr_root(l) {}
336
343 Iterator& operator=(std::shared_ptr<node> current) {
344 this->curr_root = current;
345 return *(this);
346 }
347
354 if (curr_root) {
355 curr_root = curr_root->next;
356 }
357 return *(this);
358 }
359
366 Iterator it = *this;
367 ++*(this);
368 return it;
369 }
370
377 if (curr_root) {
378 curr_root = curr_root->prev;
379 }
380 return *(this);
381 }
382
389 Iterator it = *this;
390 --*(this);
391 return it;
392 }
393
401 bool operator!=(const Iterator& it) { return curr_root != it.curr_root; }
402
408 T operator*() { return curr_root->val; }
409};
410
411#endif
Iterator class.
Definition doubly_linked_list.h:325
Iterator operator--(int)
operator – for type iterator
Definition doubly_linked_list.h:388
Iterator operator++(int)
operator ++ for type Iterator
Definition doubly_linked_list.h:365
Iterator & operator=(std::shared_ptr< node > current)
= operator for Iterator type
Definition doubly_linked_list.h:343
Iterator(const std::shared_ptr< node > &l) noexcept
Construct a new Iterator object.
Definition doubly_linked_list.h:335
Iterator & operator--()
operator – for type Iterator
Definition doubly_linked_list.h:376
bool operator!=(const Iterator &it)
operator != for type Iterator
Definition doubly_linked_list.h:401
T operator*()
operator * for type Iterator
Definition doubly_linked_list.h:408
Iterator & operator++()
operator ++ for type Iterator
Definition doubly_linked_list.h:353
Iterator end()
pointer that points to end
Definition doubly_linked_list.h:80
void push_back(T key)
push_back function.
Definition doubly_linked_list.h:172
doubly_linked_list & operator=(const doubly_linked_list &l)
operator = for doubly linked list class
Definition doubly_linked_list.h:47
doubly_linked_list(std::vector< T > _elements={}) noexcept
doubly_linked_list class constructor
Definition doubly_linked_list.h:26
doubly_linked_list(const doubly_linked_list &l)
copy constructor for the doubly_linked_list class
Definition doubly_linked_list.h:39
bool empty()
empty function.
Definition doubly_linked_list.h:58
size_t size()
size function. Returns the size of the list.
Definition doubly_linked_list.h:64
void push_front(T key)
push_front function.
Definition doubly_linked_list.h:186
void visualize()
visualize function returns a .dot file that can be previewd with graphviz plugin in vscode
void reverse()
reverse function. reverses the linked list.
Definition doubly_linked_list.h:238
Iterator begin()
pointer that points to begin
Definition doubly_linked_list.h:73
friend std::ostream & operator<<(std::ostream &out, doubly_linked_list< T > &l)
<< operator for the doubly_linked_list class.
Definition doubly_linked_list.h:128
bool search(T key)
search function.
Definition doubly_linked_list.h:159
std::vector< T > elements()
elements function.
Definition doubly_linked_list.h:225
void erase(T key)
erase function.
Definition doubly_linked_list.h:200