AlgoPlus v0.1.0
Loading...
Searching...
No Matches
circular_linked_list.h
1#ifndef CIRCULAR_LINKED_LIST_H
2#define CIRCULAR_LINKED_LIST_H
3
4#ifdef ENABLE_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 <type_traits>
12#include <vector>
13#endif
14
18template <typename T> class circular_linked_list {
19 public:
25 inline explicit circular_linked_list(std::vector<T> _elements = {}) noexcept
26 : root(nullptr), tail(nullptr) {
27 if (!_elements.empty()) {
28 for (T& x : _elements) {
29 this->push_back(x);
30 }
31 }
32 }
33
39 : root(c.root), tail(c.tail), _size(c._size) {}
40
47 root = c.root;
48 tail = c.tail;
49 _size = c._size;
50 return *this;
51 }
52
59 inline bool empty() { return root == nullptr; }
60
66 inline size_t size() { return _size; }
67
68 class Iterator;
69
75 inline Iterator begin() { return Iterator(root); }
76
82 inline Iterator end() { return Iterator(nullptr); }
83
89 void push_back(T key);
90
96 void push_front(T key);
97
103 void erase(T key);
104
112 bool search(T key);
113
119 std::vector<T> elements();
120
125 void visualize();
126
130 friend std::ostream& operator<<(std::ostream& out, circular_linked_list<T>& l1) {
131 out << '{';
132 std::shared_ptr<node> head = l1.root;
133 do {
134 out << head->val << ' ';
135 head = head->next;
136 } while (head != l1.root);
137 out << '}' << '\n';
138 return out;
139 }
140
141 private:
147 struct node {
148 T val;
149 std::shared_ptr<node> next;
150 node(T key = 0) : val(key), next(nullptr) {}
151 };
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> inline void circular_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 tail = p;
165 } else {
166 tail->next = p;
167 tail = p;
168 }
169 tail->next = root;
170 _size++;
171}
172
173template <typename T> inline void circular_linked_list<T>::push_front(T key) {
174 std::shared_ptr<node> p = std::make_shared<node>(key);
175 if (root == nullptr) {
176 root = p;
177 tail = p;
178 } else {
179 p->next = root;
180 root = p;
181 tail->next = root;
182 }
183 _size++;
184}
185
186template <typename T> inline void circular_linked_list<T>::erase(T key) {
187 if (empty()) {
188 return;
189 }
190
191 std::shared_ptr<node> t = root;
192 std::shared_ptr<node> to_be_removed = nullptr;
193
194 do {
195 if (t->next->val == key) {
196 to_be_removed = t->next;
197 t->next = t->next->next;
198 to_be_removed.reset();
199 _size--;
200
201 if (t->next == root) {
202 tail = t;
203 }
204
205 if (root == tail) {
206 tail = nullptr;
207 }
208
209 return;
210 }
211
212 t = t->next;
213 } while (t != root);
214}
215
216template <typename T> inline bool circular_linked_list<T>::search(T key) {
217 try {
218 if (empty()) {
219 return false;
220 } else {
221 std::shared_ptr<node> t = root;
222 do {
223 if (t->val == key) {
224 return true;
225 }
226 t = t->next;
227 } while (t != root);
228
229 return false;
230 }
231 } catch (std::invalid_argument& e) {
232 std::cerr << e.what() << '\n';
233 return false;
234 }
235}
236
237template <typename T> inline std::vector<T> circular_linked_list<T>::elements() {
238 std::vector<T> _elements;
239
240 if (this->empty()) {
241 return _elements;
242 }
243
244 std::shared_ptr<node> head = root;
245 do {
246 _elements.push_back(head->val);
247 head = head->next;
248 } while (head != root);
249
250 return _elements;
251}
252
253template <typename T> inline std::string circular_linked_list<T>::generate() {
254 std::string gen;
255 gen += "rankdir=LR;";
256 gen += '\n';
257 gen += "node [shape=record;]";
258 gen += '\n';
259 std::vector<T> els = this->elements();
260 if (std::is_same_v<T, std::string> || std::is_same_v<T, char>) {
261 for (auto& x : els) {
262 gen += x;
263 gen += " [label=<{ ";
264 gen += x;
265 gen += " | }>] ;";
266 gen += '\n';
267 }
268
269 std::shared_ptr<node> curr = root;
270 while (curr->next) {
271 gen += curr->val;
272 gen += ":ref -> ";
273 gen += curr->next->val;
274 gen += ":data [arrowhead=vee, arrowtail=dot, dir=both];";
275 gen += '\n';
276 curr = curr->next;
277 if (curr == root) {
278 break;
279 }
280 }
281 } else {
282 for (auto& x : els) {
283 gen += std::to_string(x);
284 gen += " [label=<{ ";
285 gen += std::to_string(x);
286 gen += " | }>] ;";
287 gen += '\n';
288 }
289
290 std::shared_ptr<node> curr = root;
291 while (curr->next) {
292 gen += std::to_string(curr->val);
293 gen += ":ref -> ";
294 gen += std::to_string(curr->next->val);
295 gen += ":data [arrowhead=vee, arrowtail=dot, dir=both];";
296 gen += '\n';
297 curr = curr->next;
298 if (curr == root) {
299 break;
300 }
301 }
302 }
303 return gen;
304}
305
306#ifdef ENABLE_LIST_VISUALIZATION
307template <typename T> void circular_linked_list<T>::visualize() {
308 std::string generated = this->generate();
309 linked_list_visualization::visualize(generated);
310}
311#endif
312
316template <typename T> class circular_linked_list<T>::Iterator {
317 private:
318 std::shared_ptr<node> curr_root;
319
320 public:
326 explicit Iterator(const std::shared_ptr<node>& l) noexcept : curr_root(l) {}
327
334 Iterator& operator=(std::shared_ptr<node> current) {
335 this->curr_root = current;
336 return *(this);
337 }
338
345 if (curr_root) {
346 curr_root = curr_root->next;
347 }
348 return *(this);
349 }
350
357 Iterator it = *this;
358 ++*(this);
359 return it;
360 }
361
369 bool operator!=(const Iterator& it) { return curr_root != it.curr_root; }
370
376 T operator*() { return curr_root->val; }
377};
378#endif
Iterator class.
Definition circular_linked_list.h:316
Iterator & operator++()
operator ++ for type Iterator
Definition circular_linked_list.h:344
T operator*()
operator * for type Iterator
Definition circular_linked_list.h:376
Iterator(const std::shared_ptr< node > &l) noexcept
Construct a new Iterator object.
Definition circular_linked_list.h:326
Iterator & operator=(std::shared_ptr< node > current)
= operator for Iterator type
Definition circular_linked_list.h:334
bool operator!=(const Iterator &it)
operator != for type Iterator
Definition circular_linked_list.h:369
Iterator operator++(int)
operator ++ for type Iterator
Definition circular_linked_list.h:356
bool search(T key)
search function
Definition circular_linked_list.h:216
void push_back(T key)
push_back function
Definition circular_linked_list.h:160
Iterator begin()
pointer that points to begin
Definition circular_linked_list.h:75
std::vector< T > elements()
elements function
Definition circular_linked_list.h:237
void erase(T key)
erase function
Definition circular_linked_list.h:186
void push_front(T key)
push_front function
Definition circular_linked_list.h:173
circular_linked_list & operator=(const circular_linked_list &c)
operator = for circular linked list class
Definition circular_linked_list.h:46
Iterator end()
pointer that points to end
Definition circular_linked_list.h:82
friend std::ostream & operator<<(std::ostream &out, circular_linked_list< T > &l1)
<< operator for the circular list class
Definition circular_linked_list.h:130
circular_linked_list(const circular_linked_list &c)
copy constructor for the circular linked list class
Definition circular_linked_list.h:38
size_t size()
size function
Definition circular_linked_list.h:66
void visualize()
visualize function returns a .dot file that can be previewd with graphviz plugin in vscode
bool empty()
empty function
Definition circular_linked_list.h:59
circular_linked_list(std::vector< T > _elements={}) noexcept
Construct a new circular linked list object.
Definition circular_linked_list.h:25