AlgoPlus v0.1.0
Loading...
Searching...
No Matches
linked_list.h
1#ifndef LINKED_LIST_H
2#define 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
19
20template <typename T> class linked_list {
21 public:
27 inline 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 inline explicit linked_list(const linked_list& l)
41 : root(l.root), tail(l.tail), _size(l._size) {}
42
48 inline linked_list& operator=(const linked_list& l) {
49 root = l.root;
50 tail = l.tail;
51 _size = l._size;
52 return *this;
53 }
54
59 inline bool empty() { return root == nullptr; }
60
65 inline size_t size() { return _size; }
66
67 class Iterator;
68
74 inline Iterator begin() { return Iterator(root); }
75
81 inline Iterator end() { return Iterator(nullptr); }
82
87 void push_back(T key);
88
93 void push_front(T key);
94
99 void erase(T key);
100
106 bool search(T key);
107
112 std::vector<T> elements();
113
117 void reverse();
118
123 void visualize();
124
128 inline friend std::ostream& operator<<(std::ostream& out, linked_list<T>& l1) {
129 out << '{';
130 std::shared_ptr<node> head = l1.root;
131 while (head) {
132 out << head->val << ' ';
133 head = head->next;
134 }
135 out << '}' << '\n';
136 return out;
137 }
138
139 private:
145 struct node {
146 T val;
147 std::shared_ptr<node> next;
148 node(T key = 0) : val(key), next(nullptr) {}
149 };
150 std::shared_ptr<node> root;
151 std::shared_ptr<node> tail;
152 size_t _size{0};
153
154 std::string generate();
155};
156
157template <typename T> inline void linked_list<T>::push_back(T key) {
158 std::shared_ptr<node> p = std::make_shared<node>(key);
159 if (root == nullptr) {
160 root = p;
161 } else {
162 tail->next = p;
163 }
164 tail = p;
165 _size++;
166}
167
168template <typename T> inline void linked_list<T>::push_front(T key) {
169 std::shared_ptr<node> p = std::make_shared<node>(key);
170 p->next = root;
171 if (tail == nullptr) {
172 tail = root;
173 }
174 root = p;
175 _size++;
176}
177
178template <typename T> inline void linked_list<T>::erase(T key) {
179 if (empty()) {
180 return;
181 }
182 std::shared_ptr<node> t = root;
183 std::shared_ptr<node> to_be_removed = nullptr;
184 while (t != tail && t->next->val != key) {
185 t = t->next;
186 }
187 if (t == tail) {
188 return;
189 }
190 to_be_removed = t->next;
191 t->next = t->next->next;
192 to_be_removed.reset();
193 if (t->next == nullptr) {
194 tail = t;
195 }
196 if (root == tail) {
197 tail = nullptr;
198 }
199 _size--;
200}
201
202template <typename T> inline bool linked_list<T>::search(T key) {
203 try {
204 if (empty()) {
205 return false;
206 } else {
207 std::shared_ptr<node> t = root;
208 while (t != tail && t->val != key) {
209 t = t->next;
210 }
211 if (t == tail || t == nullptr) {
212 return false;
213 }
214 return true;
215 }
216 } catch (std::invalid_argument& e) {
217 std::cerr << e.what() << '\n';
218 return false;
219 }
220}
221
222template <typename T> inline std::vector<T> linked_list<T>::elements() {
223 std::vector<T> _elements;
224
225 if (this->empty()) {
226 return _elements;
227 }
228 std::shared_ptr<node> head = root;
229 while (head) {
230 _elements.push_back(head->val);
231 head = head->next;
232 }
233 return _elements;
234}
235
236template <typename T> inline void linked_list<T>::reverse() {
237 std::shared_ptr<node> current = root;
238 std::shared_ptr<node> prev{nullptr}, next{nullptr};
239
240 while (current != nullptr) {
241 next = current->next;
242 current->next = prev;
243 prev = current;
244 current = next;
245 }
246 root = prev;
247}
248
249template <typename T> inline std::string linked_list<T>::generate() {
250 std::string gen;
251 gen += "rankdir=LR;";
252 gen += '\n';
253 gen += "node [shape=record;]";
254 gen += '\n';
255 std::vector<T> els = this->elements();
256 if (std::is_same_v<T, std::string> || std::is_same_v<T, char>) {
257 for (auto& x : els) {
258 gen += x;
259 gen += " [label=<{ ";
260 gen += x;
261 gen += " | }>] ;";
262 gen += '\n';
263 }
264
265 std::shared_ptr<node> curr = root;
266 while (curr->next) {
267 gen += curr->val;
268 gen += ":ref -> ";
269 gen += curr->next->val;
270 gen += ":data [arrowhead=vee, arrowtail=dot, dir=both];";
271 gen += '\n';
272 curr = curr->next;
273 }
274 } else {
275 for (auto& x : els) {
276 gen += std::to_string(x);
277 gen += " [label=<{ ";
278 gen += std::to_string(x);
279 gen += " | }>] ;";
280 gen += '\n';
281 }
282
283 std::shared_ptr<node> curr = root;
284 while (curr->next) {
285 gen += std::to_string(curr->val);
286 gen += ":ref -> ";
287 gen += std::to_string(curr->next->val);
288 gen += ":data [arrowhead=vee, arrowtail=dot, dir=both];";
289 gen += '\n';
290 curr = curr->next;
291 }
292 }
293 return gen;
294}
295
296#ifdef ENABLE_LINKED_LIST_VISUALIZATION
297template <typename T> inline void linked_list<T>::visualize() {
298 std::string generated = this->generate();
299 linked_list_visualization::visualize(generated);
300}
301#endif
302
306template <typename T> class linked_list<T>::Iterator {
307 private:
308 std::shared_ptr<node> curr_root;
309
310 public:
316 explicit Iterator(const std::shared_ptr<node>& l) noexcept : curr_root(l) {}
317
324 Iterator& operator=(std::shared_ptr<node> current) {
325 this->curr_root = current;
326 return *(this);
327 }
328
335 if (curr_root) {
336 curr_root = curr_root->next;
337 }
338 return *(this);
339 }
340
347 Iterator it = *this;
348 ++*(this);
349 return it;
350 }
351
359 bool operator!=(const Iterator& it) { return curr_root != it.curr_root; }
360
366 T operator*() { return curr_root->val; }
367};
368
369#endif
Iterator class.
Definition linked_list.h:306
Iterator(const std::shared_ptr< node > &l) noexcept
Construct a new Iterator object.
Definition linked_list.h:316
Iterator & operator++()
operator ++ for type Iterator
Definition linked_list.h:334
Iterator & operator=(std::shared_ptr< node > current)
= operator for Iterator type
Definition linked_list.h:324
T operator*()
operator * for type Iterator
Definition linked_list.h:366
Iterator operator++(int)
operator ++ for type Iterator
Definition linked_list.h:346
bool operator!=(const Iterator &it)
operator != for type Iterator
Definition linked_list.h:359
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:168
void reverse()
reverse function.
Definition linked_list.h:236
bool search(T key)
search function.
Definition linked_list.h:202
Iterator begin()
pointer that points to begin
Definition linked_list.h:74
void erase(T key)
erase function.
Definition linked_list.h:178
void push_back(T key)
push_back function.
Definition linked_list.h:157
friend std::ostream & operator<<(std::ostream &out, linked_list< T > &l1)
<< operator for the linked_list class.
Definition linked_list.h:128
Iterator end()
pointer that points to end
Definition linked_list.h:81
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:59
size_t size()
size function. Returns the size of the list.
Definition linked_list.h:65
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:222
linked_list & operator=(const linked_list &l)
operator = for linked list class
Definition linked_list.h:48