AlgoPlus v0.1.0
Loading...
Searching...
No Matches
linked_list.h
1#ifndef LINKED_LIST_H
2#define 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
20template <typename T> class linked_list {
21 public:
27 explicit linked_list(std::vector<T> _elements = {}) noexcept
28 : root(nullptr), tail(nullptr) {
29 if (!_elements.empty()) {
30 for (T &x : _elements) {
31 this->push_back(x);
32 }
33 }
34 }
35
40 explicit linked_list(const linked_list &l) : root(l.root), tail(l.tail), _size(l._size) {
41
42
43
44 }
45
52 root = l.root;
53 tail = l.tail;
54 _size = l._size;
55 return *this;
56 }
57
62 bool empty() { return root == nullptr; }
63
68 size_t size() { return _size; }
69
70 class Iterator;
71
77 Iterator begin() { return Iterator(root); }
78
84 Iterator end() { return Iterator(nullptr); }
85
90 void push_back(T key);
91
96 void push_front(T key);
97
102 void erase(T key);
103
109 bool search(T key);
110
115 std::vector<T> elements();
116
120 void reverse();
121
126 void visualize();
127
131 friend std::ostream &operator<<(std::ostream &out, linked_list<T> &l1) {
132 out << '{';
133 std::shared_ptr<node> head = l1.root;
134 while (head) {
135 out << head->val << ' ';
136 head = head->next;
137 }
138 out << '}' << '\n';
139 return out;
140 }
141
142 private:
148 struct node {
149 T val;
150 std::shared_ptr<node> next;
151 node(T key = 0) : val(key), next(nullptr) {}
152 };
153 std::shared_ptr<node> root;
154 std::shared_ptr<node> tail;
155 size_t _size{0};
156
157 std::string generate();
158};
159
160template <typename T> void linked_list<T>::push_back(T key) {
161 std::shared_ptr<node> p = std::make_shared<node>(key);
162 if (root == nullptr) {
163 root = p;
164 } else {
165 tail->next = p;
166 }
167 tail = p;
168 _size++;
169}
170
171template <typename T> void linked_list<T>::push_front(T key) {
172 std::shared_ptr<node> p = std::make_shared<node>(key);
173 p->next = root;
174 if(tail == nullptr) { tail = root; }
175 root = p;
176 _size++;
177}
178
179template <typename T> void linked_list<T>::erase(T key) {
180 if (empty()) {
181 return;
182 }
183 std::shared_ptr<node> t = root;
184 std::shared_ptr<node> to_be_removed = nullptr;
185 while (t != tail && t->next->val != key) {
186 t = t->next;
187 }
188 if (t == tail) {
189 return;
190 }
191 to_be_removed = t->next;
192 t->next = t->next->next;
193 to_be_removed.reset();
194 if (t->next == nullptr) {
195 tail = t;
196 }
197 if (root == tail) {
198 tail = nullptr;
199 }
200 _size--;
201}
202
203template <typename T> bool linked_list<T>::search(T key) {
204 try {
205 if (empty()) {
206 return false;
207 } else {
208 std::shared_ptr<node> t = root;
209 while (t != tail && t->val != key) {
210 t = t->next;
211 }
212 if (t == tail || t == nullptr) {
213 return false;
214 }
215 return true;
216 }
217 } catch (std::invalid_argument &e) {
218 std::cerr << e.what() << '\n';
219 return false;
220 }
221}
222
223template <typename T> std::vector<T> linked_list<T>::elements() {
224 std::vector<T> _elements;
225
226 if (this->empty()) {
227 return _elements;
228 }
229 std::shared_ptr<node> head = root;
230 while (head) {
231 _elements.push_back(head->val);
232 head = head->next;
233 }
234 return _elements;
235}
236
237template <typename T> void linked_list<T>::reverse() {
238 std::shared_ptr<node> current = root;
239 std::shared_ptr<node> prev{nullptr}, next{nullptr};
240
241 while (current != nullptr) {
242 next = current->next;
243 current->next = prev;
244 prev = current;
245 current = next;
246 }
247 root = prev;
248}
249
250template <typename T> std::string linked_list<T>::generate() {
251 std::string gen;
252 gen += "rankdir=LR;";
253 gen += '\n';
254 gen += "node [shape=record;]";
255 gen += '\n';
256 std::vector<T> els = this->elements();
257 if (std::is_same_v<T, std::string> || std::is_same_v<T, char>) {
258 for (auto &x : els) {
259 gen += x;
260 gen += " [label=<{ ";
261 gen += x;
262 gen += " | }>] ;";
263 gen += '\n';
264 }
265
266 std::shared_ptr<node> curr = root;
267 while (curr->next) {
268 gen += curr->val;
269 gen += ":ref -> ";
270 gen += curr->next->val;
271 gen += ":data [arrowhead=vee, arrowtail=dot, dir=both];";
272 gen += '\n';
273 curr = curr->next;
274 }
275 } else {
276 for (auto &x : els) {
277 gen += std::to_string(x);
278 gen += " [label=<{ ";
279 gen += std::to_string(x);
280 gen += " | }>] ;";
281 gen += '\n';
282 }
283
284 std::shared_ptr<node> curr = root;
285 while (curr->next) {
286 gen += std::to_string(curr->val);
287 gen += ":ref -> ";
288 gen += std::to_string(curr->next->val);
289 gen += ":data [arrowhead=vee, arrowtail=dot, dir=both];";
290 gen += '\n';
291 curr = curr->next;
292 }
293 }
294 return gen;
295}
296
297#ifdef LINKED_LIST_VISUALIZATION_H
298template <typename T> void linked_list<T>::visualize() {
299 std::string generated = this->generate();
300 linked_list_visualization::visualize(generated);
301}
302#endif
303
304
308template <typename T> class linked_list<T>::Iterator {
309 private:
310 std::shared_ptr<node> curr_root;
311
312 public:
318 explicit Iterator(const std::shared_ptr<node> &l) noexcept : curr_root(l) {}
319
326 Iterator &operator=(std::shared_ptr<node> current) {
327 this->curr_root = current;
328 return *(this);
329 }
330
337 if (curr_root) {
338 curr_root = curr_root->next;
339 }
340 return *(this);
341 }
342
349 Iterator it = *this;
350 ++*(this);
351 return it;
352 }
353
361 bool operator!=(const Iterator &it) { return curr_root != it.curr_root; }
362
368 T operator*() { return curr_root->val; }
369};
370
371#endif
Iterator class.
Definition linked_list.h:308
Iterator(const std::shared_ptr< node > &l) noexcept
Construct a new Iterator object.
Definition linked_list.h:318
Iterator & operator++()
operator ++ for type Iterator
Definition linked_list.h:336
Iterator & operator=(std::shared_ptr< node > current)
= operator for Iterator type
Definition linked_list.h:326
T operator*()
operator * for type Iterator
Definition linked_list.h:368
Iterator operator++(int)
operator ++ for type Iterator
Definition linked_list.h:348
bool operator!=(const Iterator &it)
operator != for type Iterator
Definition linked_list.h:361
single linked list class
Definition linked_list.h:20
linked_list(const linked_list &l)
copy constructor for the linked_list class
Definition linked_list.h:40
void push_front(T key)
push_front function.
Definition linked_list.h:171
void reverse()
reverse function.
Definition linked_list.h:237
bool search(T key)
search function.
Definition linked_list.h:203
Iterator begin()
pointer that points to begin
Definition linked_list.h:77
void erase(T key)
erase function.
Definition linked_list.h:179
void push_back(T key)
push_back function.
Definition linked_list.h:160
friend std::ostream & operator<<(std::ostream &out, linked_list< T > &l1)
<< operator for the linked_list class.
Definition linked_list.h:131
Iterator end()
pointer that points to end
Definition linked_list.h:84
void visualize()
visualize function returns a .dot file that can be previewd with graphviz plugin in vscode
bool empty()
empty function. Returns true if the list is empty.
Definition linked_list.h:62
size_t size()
size function. Returns the size of the list.
Definition linked_list.h:68
linked_list(std::vector< T > _elements={}) noexcept
linked_list class constructor
Definition linked_list.h:27
std::vector< T > elements()
elements function.
Definition linked_list.h:223
linked_list & operator=(const linked_list &l)
operator = for linked list class
Definition linked_list.h:51