AlgoPlus v0.1.0
Loading...
Searching...
No Matches
frequency_list.h
1#ifndef FREQUENCY_LIST_H
2#define FREQUENCY_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 <cstdint>
10#include <vector>
11#include <memory>
12#include <string>
13#include <iostream>
14#endif
15
16
30template<typename T>
32 public:
43 explicit frequency_list(std::vector<T> data = {}) noexcept
44 : head(nullptr), tail(nullptr) {
45 if(!data.empty()) {
46 for (const auto &item: data) {
47 this->push_back(item);
48 }
49 }
50 }
51
60 frequency_list(const frequency_list<T> &list) : head(nullptr), tail(nullptr), size(0) {
61 for (auto iter = list.head; iter != nullptr; iter = iter->next) {
62 this->push_back(iter->data);
63 }
64 }
65
66 class Iterator;
67
78 void push_back(T data);
79
89 void push_front(T data);
90
101 bool search(T key);
102
109 int64_t get_frequency(T key);
110
111
121 void erase(T key);
122
126 void reset_frequency();
127
128
134 std::vector<std::pair<T, int64_t> > elements();
135
136
142 bool empty() { return head == nullptr; }
143
151 Iterator begin() { return Iterator(head); }
152
161 Iterator end() { return Iterator(nullptr); }
162
168 void visualize();
169
181 friend std::ostream& operator<<(std::ostream& os, const frequency_list<T>& flist) {
182 auto iterator = flist.head;
183 while (iterator != nullptr) {
184 os << iterator->data << "(" << iterator->freq << ") ";
185 iterator = iterator->next;
186 }
187 return os;
188 }
189
190 private:
191 struct node {
192 T data;
193 int64_t freq;
194 std::shared_ptr<node> next;
195 std::weak_ptr<node> prev;
196
197 node(T data, int64_t freq, std::weak_ptr<node> prev, std::shared_ptr<node> next)
198 : data(data), freq(freq), prev(prev), next(next) {}
199
200 void add_freq() { freq++; }
201 void reset_freq() { freq = 1; }
202 };
203
204 std::shared_ptr<node> head;
205 node *tail;
206 uint64_t size{0};
207
218 void update_list_sequence();
219
230 void swap_nodes(std::shared_ptr<node> a, std::shared_ptr<node> b);
231
237 std::string generate();
238};
239
240
241
242template<typename T>
243void frequency_list<T>::swap_nodes(std::shared_ptr<node> a, std::shared_ptr<node> b) {
244 if(a == nullptr || b == nullptr || a->next != b)
245 return;
246
247 // Attach b's next to a and a's prev to b
248 a->next = b->next;
249 b->prev = a->prev;
250
251 // If b's next exists, attach a to its prev
252 if(b->next)
253 b->next->prev = a;
254
255 // If a's prev exists(i.e., a is not the head), attach b to its next
256 if(a->prev.lock())
257 a->prev.lock()->next = b;
258
259 // Now, attach a to b's next and b to a's prev
260 b->next = a;
261 a->prev = b;
262
263 // If the node a was the head node, update the head to b
264 if (head == a)
265 head = b;
266}
267
268template<typename T>
270 auto current_node = head;
271
272 while (current_node != nullptr && current_node->next != nullptr) {
273 if (current_node->freq < current_node->next->freq) {
274 swap_nodes(current_node, current_node->next);
275
276 if(current_node->prev.lock())
277 current_node = current_node->prev.lock();
278
279 } else
280 current_node = current_node->next;
281 }
282}
283
284template<typename T>
286 auto iterator = head;
287
288 while (iterator != nullptr) {
289 iterator->reset_freq();
290 iterator = iterator->next;
291 }
292}
293
294
295template<typename T>
297 auto Iterator = head;
298
299 // Iterating over the list to find if the same data is already present
300 while (Iterator != nullptr) {
301 if (Iterator->data == data) {
302 // if data is found, increase frequency and re-sort the list
303 Iterator->freq++;
304 update_list_sequence();
305 return;
306 }
307 Iterator = Iterator->next;
308 }
309
310 // if data is not found in the list, add new node at front
311 auto new_node = std::make_shared<node>(data, 1, std::weak_ptr<node>(), head);
312
313 if (head != nullptr) {
314 head->prev = new_node;
315 }
316
317 head = new_node;
318
319 size++;
320}
321
322template<typename T>
324 auto iterator = head;
325
326 // special case: deleting the head node
327 if (head != nullptr && head->data == key) {
328 head = head->next;
329 if(head)
330 head->prev.reset();
331 size--;
332 return;
333 }
334
335 // iterate over the rest nodes
336 while (iterator != nullptr) {
337 if (iterator->data == key) {
338 // connect previous node and next node
339 if(auto sharedPrev = iterator->prev.lock()){
340 sharedPrev->next = iterator->next;
341 }
342 if (iterator->next) {
343 iterator->next->prev = iterator->prev;
344 }
345 // deleting the node by falling out of scope
346 size--;
347 return;
348 }
349 iterator = iterator->next;
350 }
351}
352
353template<typename T>
355 auto iterator = head;
356
357 while(iterator != nullptr) {
358 if(iterator->data == key) {
359 return iterator->freq;
360 }
361
362 iterator = iterator->next;
363 }
364
365 return -1;
366}
367
368template<typename T>
370 auto iterator = head;
371
372 while (iterator != nullptr) {
373 if (iterator->data == key) {
374 iterator->add_freq();
375 update_list_sequence();
376 return true;
377 }
378
379 iterator = iterator->next;
380 }
381
382 return false;
383}
384
385template<typename T>
387 if (this->empty()) {
388 head = std::make_shared<node>(data, 1, std::weak_ptr<node>(), nullptr);
389 return;
390 }
391
392 auto iterator = head;
393 while (iterator) {
394 if (iterator->data == data) {
395 iterator->add_freq();
396 update_list_sequence();
397 return;
398 }
399 if (!iterator->next)
400 break;
401 iterator = iterator->next;
402 }
403
404 auto newNode = std::shared_ptr<node>(new node(data, 1, iterator, nullptr));
405 if (iterator) iterator->next = newNode;
406 size++;
407}
408
409
410template<typename T> std::vector<std::pair<T, int64_t> > frequency_list<T>::elements(){
411 std::vector<std::pair<T, int64_t> > ans;
412 std::shared_ptr<node> root = head;
413 while(root){
414 ans.push_back(std::make_pair(root -> data, root -> freq));
415 root = root -> next;
416 }
417 return ans;
418}
419
420
421template <typename T> std::string frequency_list<T>::generate() {
422 std::string gen = "";
423 gen += "rankdir=LR;";
424 gen += '\n';
425 gen += "node [shape=record;]";
426 gen += '\n';
427 std::vector<std::pair<T, int64_t> > els = this->elements();
428 if (std::is_same_v<T, std::string> || std::is_same_v<T, char>) {
429 for (auto &x : els) {
430 gen += x.first;
431 gen += " [label=<{ ";
432 gen += x.first;
433 gen += " | ";
434 gen += x.second;
435 gen += " | }>] ;";
436 gen += '\n';
437 }
438
439 std::shared_ptr<node> curr = head;
440 while (curr->next) {
441 gen += curr->data;
442 gen += ":ref -> ";
443 gen += curr->next->data;
444 gen += ":data [arrowhead=vee, arrowtail=dot, dir=both];";
445 gen += '\n';
446
447 gen += curr->next->data;
448 gen += ":data -> ";
449 gen += curr->data;
450 gen += ":ref [arrowhead=vee, arrowtail=dot, dir=both];";
451 gen += '\n';
452
453 curr = curr->next;
454 }
455 } else {
456 for (auto &x : els) {
457 std::cout << std::to_string(x.first) << " " << std::to_string(x.second) << '\n';
458 gen += std::to_string(x.first);
459 gen += " [label=<{ ";
460 gen += std::to_string(x.first);
461 gen += " | ";
462 gen += std::to_string(x.second);
463 gen += " | }>] ;";
464 gen += '\n';
465 }
466
467 std::shared_ptr<node> curr = head;
468 while (curr->next) {
469 gen += std::to_string(curr->data);
470 gen += ":ref -> ";
471 gen += std::to_string(curr->next->data);
472 gen += ":data [arrowhead=vee, arrowtail=dot, dir=both];";
473 gen += '\n';
474
475 gen += std::to_string(curr->next->data);
476 gen += ":data -> ";
477 gen += std::to_string(curr->data);
478 gen += ":ref [arrowhead=vee, arrowtail=dot, dir=both];";
479 gen += '\n';
480
481 curr = curr->next;
482 }
483 }
484 return gen;
485}
486
487#ifdef LINKED_LIST_VISUALIZATION_H
488template <typename T> void frequency_list<T>::visualize() {
489 std::string generated = this->generate();
490 linked_list_visualization::visualize(generated);
491}
492#endif
493
494
495
496template<typename T>
498 private:
499 std::shared_ptr<node> current;
500 public:
506 explicit Iterator(const std::shared_ptr<node> &ptr) noexcept
507 : current(ptr) {}
508
509
519 Iterator &operator=(const std::shared_ptr<node> &ptr) {
520 current = ptr;
521 return *this;
522 }
523
533 if(current) {
534 current = current->next;
535 }
536 return *this;
537 }
538
548 Iterator tmp = *(this);
549 ++*(this);
550 return tmp;
551 }
552
561 Iterator & operator --(){
562 if(current){
563 current = current -> prev;
564 }
565 return *(this);
566 }
567
575 Iterator operator --(int){
576 Iterator tmp = *(this);
577 --*(this);
578 return tmp;
579 }
580
589 bool operator==(const Iterator &it) { return it.current == this->current; }
590
599 bool operator!=(const Iterator &it) { return it.current != this->current; }
600
606 T operator*() { return current->data; }
607
608};
609
610#endif //FREQUENCY_LIST_H
Definition frequency_list.h:497
T operator*()
Dereference operator for the Iterator class.
Definition frequency_list.h:606
Iterator & operator=(const std::shared_ptr< node > &ptr)
Assignment operator for the Iterator class.
Definition frequency_list.h:519
Iterator & operator++()
Pre-increment operator for the Iterator class.
Definition frequency_list.h:532
Iterator(const std::shared_ptr< node > &ptr) noexcept
Iterator class for a linked list.
Definition frequency_list.h:506
Iterator operator++(int)
Post-increment operator for the Iterator class.
Definition frequency_list.h:547
bool operator==(const Iterator &it)
Equality operator for the Iterator class.
Definition frequency_list.h:589
bool operator!=(const Iterator &it)
Inequality operator for the Iterator class.
Definition frequency_list.h:599
Self-learning Frequency List that maintains a list of elements in descending order of their frequency...
Definition frequency_list.h:31
bool empty()
Checks if the frequency list is empty.
Definition frequency_list.h:142
void push_front(T data)
Adds an element to the front of the frequency list.
Definition frequency_list.h:296
void erase(T key)
Removes the first occurrence of a given key in the frequency list.
Definition frequency_list.h:323
int64_t get_frequency(T key)
Gets the frequency of a key in the frequency list.
Definition frequency_list.h:354
Iterator begin()
Get an iterator pointing to the beginning of the frequency list.
Definition frequency_list.h:151
friend std::ostream & operator<<(std::ostream &os, const frequency_list< T > &flist)
Overloaded output stream insertion operator for the frequency_list class.
Definition frequency_list.h:181
bool search(T key)
Searches for a given key in the frequency list.
Definition frequency_list.h:369
std::vector< std::pair< T, int64_t > > elements()
Returns all the elements of the list.
Definition frequency_list.h:410
void reset_frequency()
Resets the frequency of all nodes in the frequency list to 1.
Definition frequency_list.h:285
Iterator end()
Get an iterator pointing to the end of the frequency list.
Definition frequency_list.h:161
frequency_list(const frequency_list< T > &list)
Copy constructor for the frequency_list class.
Definition frequency_list.h:60
void push_back(T data)
Adds an element to the back of the frequency list.
Definition frequency_list.h:386
void visualize()
visualize function for frequency_list Class returns a .dot file that can be previewd with graphviz pl...
frequency_list(std::vector< T > data={}) noexcept
Constructs a frequency_list object with an optional initializer list of elements.
Definition frequency_list.h:43