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 LINKED_LIST_VISUALIZATION_H
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 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 explicit doubly_linked_list(const doubly_linked_list &l) : root(l.root), tail(l.tail), _size(l._size) {
40
41
42
43 }
44
51 root = l.root;
52 tail = l.tail;
53 _size = l._size;
54 return *this;
55 }
56
61 bool empty() { return root == nullptr; }
62
67 size_t size() { return _size; }
68
69 class Iterator;
70
76 Iterator begin() { return Iterator(root); }
77
83 Iterator end() { return Iterator(nullptr); }
84
90 bool search(T key);
91
96 void push_back(T key);
97
102 void push_front(T key);
103
108 void erase(T key);
109
114 std::vector<T> elements();
115
120 void reverse();
121
126 void visualize();
127
131 friend std::ostream &operator<<(std::ostream &out, doubly_linked_list<T> &l) {
132 out << '{';
133 std::shared_ptr<node> head = l.root;
134 while (head) {
135 out << head->val << ' ';
136 head = head->next;
137 }
138 out << '}' << '\n';
139 return out;
140 }
141
142 private:
149 struct node {
150 T val;
151 std::shared_ptr<node> next;
152 std::shared_ptr<node> prev;
153 node(T key = 0) : val(key), next(nullptr), prev(nullptr) {}
154 };
155 std::shared_ptr<node> root;
156 std::shared_ptr<node> tail;
157 size_t _size{0};
158
159 std::string generate();
160};
161
162template <typename T> bool doubly_linked_list<T>::search(T key) {
163 if (this->empty()) {
164 return false;
165 } else {
166 std::shared_ptr<node> t = root;
167 while (t != nullptr && t->val != key) {
168 t = t->next;
169 }
170 return (t == nullptr || t->val != key) ? false : true;
171 }
172 return false;
173}
174
175template <typename T> void doubly_linked_list<T>::push_back(T key) {
176 std::shared_ptr<node> p = std::make_shared<node>(key);
177 p->prev = tail;
178 p->next = nullptr;
179 if (tail != nullptr) {
180 tail->next = p;
181 }
182 if (root == nullptr) {
183 root = p;
184 }
185 tail = p;
186 _size++;
187}
188
189template <typename T> void doubly_linked_list<T>::push_front(T key) {
190 std::shared_ptr<node> p = std::make_shared<node>(key);
191 p->next = root;
192 p->prev = nullptr;
193 if (root != nullptr) {
194 root->prev = p;
195 }
196 if(tail == nullptr) {
197 tail = p;
198 }
199 root = p;
200 _size++;
201}
202
203template <typename T> void doubly_linked_list<T>::erase(T key) {
204 if (root == nullptr) {
205 return;
206 }
207 std::shared_ptr<node> head = root;
208 while (head && head->val != key) {
209 head = head->next;
210 }
211 if (head == nullptr) {
212 return;
213 }
214 if (head->next != nullptr) {
215 if(head == root) {
216 root = root -> next;
217 }
218 head->next->prev = head->prev;
219 }
220 if (head->prev != nullptr) {
221 if(head == tail) {
222 tail = tail->prev;
223 }
224 head->prev->next = head->next;
225 }
226}
227
228template <typename T> std::vector<T> doubly_linked_list<T>::elements() {
229 std::vector<T> _elements;
230 if (this->empty()) {
231 return _elements;
232 }
233 std::shared_ptr<node> head = root;
234 while (head) {
235 _elements.push_back(head->val);
236 head = head->next;
237 }
238 return _elements;
239}
240
241template <typename T> void doubly_linked_list<T>::reverse() {
242 std::shared_ptr<node> current = root;
243 std::shared_ptr<node> temp{nullptr};
244
245 while (current != nullptr) {
246 temp = current->prev;
247 current->prev = current->next;
248 current->next = temp;
249 current = current->prev;
250 }
251
252 if (temp) {
253 root = temp->prev;
254 }
255}
256
257template <typename T> std::string doubly_linked_list<T>::generate() {
258 std::string gen;
259 gen += "rankdir=LR;";
260 gen += '\n';
261 gen += "node [shape=record;]";
262 gen += '\n';
263 std::vector<T> els = this->elements();
264 if (std::is_same_v<T, std::string> || std::is_same_v<T, char>) {
265 for (auto &x : els) {
266 gen += x;
267 gen += " [label=<{ ";
268 gen += x;
269 gen += " | }>] ;";
270 gen += '\n';
271 }
272
273 std::shared_ptr<node> curr = root;
274 while (curr->next) {
275 gen += curr->val;
276 gen += ":ref -> ";
277 gen += curr->next->val;
278 gen += ":data [arrowhead=vee, arrowtail=dot, dir=both];";
279 gen += '\n';
280
281 gen += curr->next->val;
282 gen += ":data -> ";
283 gen += curr->val;
284 gen += ":ref [arrowhead=vee, arrowtail=dot, dir=both];";
285 gen += '\n';
286
287 curr = curr->next;
288 }
289 } else {
290 for (auto &x : els) {
291 gen += std::to_string(x);
292 gen += " [label=<{ ";
293 gen += std::to_string(x);
294 gen += " | }>] ;";
295 gen += '\n';
296 }
297
298 std::shared_ptr<node> curr = root;
299 while (curr->next) {
300 gen += std::to_string(curr->val);
301 gen += ":ref -> ";
302 gen += std::to_string(curr->next->val);
303 gen += ":data [arrowhead=vee, arrowtail=dot, dir=both];";
304 gen += '\n';
305
306 gen += std::to_string(curr->next->val);
307 gen += ":data -> ";
308 gen += std::to_string(curr->val);
309 gen += ":ref [arrowhead=vee, arrowtail=dot, dir=both];";
310 gen += '\n';
311
312 curr = curr->next;
313 }
314 }
315 return gen;
316}
317
318
319#ifdef LINKED_LIST_VISUALIZATION_H
320template <typename T> void doubly_linked_list<T>::visualize() {
321 std::string generated = this->generate();
322 linked_list_visualization::visualize(generated);
323}
324#endif
325
329template <typename T> class doubly_linked_list<T>::Iterator {
330 private:
331 std::shared_ptr<node> curr_root;
332
333 public:
339 explicit Iterator(const std::shared_ptr<node> &l) noexcept : curr_root(l) {}
340
347 Iterator &operator=(std::shared_ptr<node> current) {
348 this->curr_root = current;
349 return *(this);
350 }
351
358 if (curr_root) {
359 curr_root = curr_root->next;
360 }
361 return *(this);
362 }
363
370 Iterator it = *this;
371 ++*(this);
372 return it;
373 }
374
381 if (curr_root) {
382 curr_root = curr_root->prev;
383 }
384 return *(this);
385 }
386
393 Iterator it = *this;
394 --*(this);
395 return it;
396 }
397
405 bool operator!=(const Iterator &it) { return curr_root != it.curr_root; }
406
412 T operator*() { return curr_root->val; }
413};
414
415#endif
Iterator class.
Definition doubly_linked_list.h:329
Iterator operator--(int)
operator – for type iterator
Definition doubly_linked_list.h:392
Iterator operator++(int)
operator ++ for type Iterator
Definition doubly_linked_list.h:369
Iterator & operator=(std::shared_ptr< node > current)
= operator for Iterator type
Definition doubly_linked_list.h:347
Iterator(const std::shared_ptr< node > &l) noexcept
Construct a new Iterator object.
Definition doubly_linked_list.h:339
Iterator & operator--()
operator – for type Iterator
Definition doubly_linked_list.h:380
bool operator!=(const Iterator &it)
operator != for type Iterator
Definition doubly_linked_list.h:405
T operator*()
operator * for type Iterator
Definition doubly_linked_list.h:412
Iterator & operator++()
operator ++ for type Iterator
Definition doubly_linked_list.h:357
doubly linked list class
Definition doubly_linked_list.h:19
Iterator end()
pointer that points to end
Definition doubly_linked_list.h:83
void push_back(T key)
push_back function.
Definition doubly_linked_list.h:175
doubly_linked_list & operator=(const doubly_linked_list &l)
operator = for doubly linked list class
Definition doubly_linked_list.h:50
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:61
size_t size()
size function. Returns the size of the list.
Definition doubly_linked_list.h:67
void push_front(T key)
push_front function.
Definition doubly_linked_list.h:189
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:241
Iterator begin()
pointer that points to begin
Definition doubly_linked_list.h:76
friend std::ostream & operator<<(std::ostream &out, doubly_linked_list< T > &l)
<< operator for the doubly_linked_list class.
Definition doubly_linked_list.h:131
bool search(T key)
search function.
Definition doubly_linked_list.h:162
std::vector< T > elements()
elements function.
Definition doubly_linked_list.h:228
void erase(T key)
erase function.
Definition doubly_linked_list.h:203