forward_list
build forward list stl from sratch
Loading...
Searching...
No Matches
forward_list.hpp
Go to the documentation of this file.
1/*
2MIT License
3
4Copyright (c) 2025 Build X From Scratch
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24#include <functional>
25#include <iostream>
26#include <initializer_list>
27#include <type_traits>
28#include <ranges>
29#include <iterator>
30#include <unordered_set>
31#include <cstddef>
32#include <limits>
33#include <concepts>
34#include <utility>
35#ifndef __forwardList
36#define __forwardList
37template <typename It>
38concept my_input_iterator = requires(It it){
39 *it; //bisa di deferencing
40 ++it; //bisa post increment
41 it++; //bisa pre increment
42};
43template <typename T,typename Allocator = std::allocator<T>>
45 private:
46 struct Node{
49 };
50 //allocator khusus node
52 typename std::allocator_traits<Allocator>::template rebind_alloc<Node>;
53 using node_traits = std::allocator_traits<node_allocator_type>;
54 node_allocator_type alloc; //instance allocator
55 Node* head = nullptr; //head pointer
56 Node* tail; //tail pointer
57 int size; //banyak element pada linked list
73 private:
74 Node* _create_node(const T& value){
75 Node* n = node_traits::allocate(alloc,1); //alokasi memory mentah sebanyak 1 blok memory untuk node(allocate)
76 try{
77 node_traits::construct(alloc,std::addressof(n->data),value); //membangun object di memory(construct)
78 }catch(...){ //catch all handler
79 node_traits::deallocate(alloc,n,1); //dealokasi
80 }
81 //set next menjadi null
82 n->next = nullptr;
83 //kembalikan node
84 return n;
85 }
86 void _destroy_node(Node* n)noexcept{
87 node_traits::destroy(alloc,std::addressof(n->data));
88 node_traits::deallocate(alloc,n,1);
89 }
90 public:
91 //default constructor allocator
94 //default constructor
95 forward_lists(const Allocator& a):
96 alloc(a),head(_create_node(T{})),tail(head),size(0){}
97
104 template <typename It>
105 requires my_input_iterator<It>
107 Node* new_node = _create_node(T{}); //create dummy node
108 head = new_node;
109 size = 0;
110 tail = head;
111 Node** curr = &head->next; //curr menunjuk head->next
112 while(begin != end){
113 Node* n_node = _create_node(*begin);
114 *curr = n_node; //isi node dengan deferencing begin
115 tail = *curr;
116 curr = &((*curr)->next); //curr = curr->next
117 ++size; //increment size
118 ++begin; //increment iterator
119 }
120 }
121
125 forward_lists(std::initializer_list<T> arr): head(nullptr){
126 Node* new_node = _create_node(T{});
127 head = new_node;
128 tail = head;
129 size = 0;
130 Node** curr = &head->next; //store alamat memory head ke curr
131 for(const T& it: arr){
132 Node* n_node = _create_node(it);
133 *curr = n_node; //curr menunjuk n_noed
134 tail = *curr; //tail ikut menunjuk curr
135 curr = &((*curr)->next); //store alamat curr->next
136 //curr selalu menunjuk ke posisi kosong
137 size++;
138 }
139 }
140 //copy constructor
142 if(others.head->next == nullptr){
143 head = nullptr;
144 return;
145 }
146 head = _create_node(T{}); //isi dummy
147 head->next = _create_node(others.head->next->data); //inialisasi data pertama
148 Node* curr = head->next; //pointer penggerak
149 Node* temp = others.head->next->next; //mulai dari node ke 2
150 while(temp != nullptr){
151 curr->next = _create_node(temp->data);
152 curr = curr->next;
153 temp = temp->next;
154 }
155 }
156 //copy assignment
158 if(this == &others){
159 return *this;
160 }
161 clear();
162 if(!others.head->next){ //nullptr
163 head = nullptr;
164 return *this;
165 }
166 head = _create_node(T{}); //isi dummy
167 head->next = _create_node(others.head->next->data);//inialisasi data pertama
168 Node* curr = head->next; //pointer penggerak
169 Node* temp = others.head->next->next; //mulai dari node ke 2
170 while(temp != nullptr){
171 curr->next = _create_node(temp->data);
172 curr = curr->next;
173 temp = temp->next;
174 }
175 return *this;
176 }
177
186 head->next = others.head->next;
187 tail = others.tail == head ? head: others.tail; //ternery operator,if you dont understand please read documentation
188 size = others.size;
189
190 //kosongkan object lama
191 others.head->next = nullptr;
192 others.tail = others.head;
193 others.size = 0;
194 }
195
199 if(this != &others){
200 clear();
201 head->next = others.head->next;
202 tail = others.tail == head ? head: others.tail; //ternery operator,if you dont understand please read documentation
203 size = others.size;
204
205 //kosongkan object lama
206 others.head->next = nullptr;
207 others.tail = others.head;
208 others.size = 0;
209 }
210 return *this;
211 }
212
218 clear(); //panggil method clear
219 }
220 private:
221 class Iterator{
222 private:
224 public:
248 using iterator_category = std::forward_iterator_tag;
249 using value_type = T;
250 using difference_type = std::ptrdiff_t;
251 using pointer = T*;
252 using reference = T&;
254 this->node = n;
255 }
256 friend std::ostream& operator<<(std::ostream& os,const Iterator& it){
257 if(it.node){
258 os << it.node->data;
259 }else{
260 os << "no output";
261 }
262 return os;
263 }
265 return node->data;
266 }
268 return node->data;
269 }
271 return &(node->data);
272 }
273 Iterator& operator++(){ //harus mengembalikan reference ke object saat ini
274 if(node) node = node->next;
275 return *this;
276 }
278 return node;
279 }
280 Iterator operator++(int){ //harus mengambalikan salin bukan referensi
281 Iterator temp = *this; //simpan keadaan sebelum di geser
282 ++(*this);//geser
283 return temp; //kembalikan keadaan sebelum di geser
284 }
285 bool operator!=(const Iterator& others)const{
286 return node != others.node;
287 }
288 bool operator==(const Iterator& others)const{
289 return node == others.node;
290 }
291 Node* get_raw()const{
292 return node;
293 }
294 };
295 public: //inialisasi Iterator
300 return Iterator(head);
301 }
302
306 return Iterator(head->next);
307 }
308
312 return Iterator(nullptr);
313 }
314 Iterator cbegin()const{//constant iterator
315 return Iterator(head->next);
316 }
317 Iterator cend()const{ //constant iterator
318 return Iterator(nullptr);
319 }
320 Iterator cbefore_begin()const{ //constant iterator
321 return Iterator(head);
322 }
323 public: //getter
328 T front(){
329 return head->next->data;
330 }
331
335 int get_size(){
336 return this->size;
337 }
338
342 bool is_empty(){
343 if(size == 0){
344 return true;
345 }
346 return false;
347 }
348
363 std::size_t max_size()const noexcept{
364 return std::numeric_limits<T>::max() / sizeof(Node);
365 }
366 T back()const noexcept{
367 return this->tail->data;
368 }
369 Allocator get_allocator()const noexcept{
370 return alloc;
371 }
372 bool check_cycle()const noexcept{
373 Node* slow = head->next;
374 Node* fast = head->next;
375 while(slow && fast && fast->next != nullptr){
376 slow = slow->next;
377 fast = fast->next->next;
378 if(fast == slow){
379 return true;
380 }
381 }
382 return false;
383 }
384 T get_middle()const noexcept{
385 Node* slow = head->next;
386 Node* fast = head->next;
387 while(slow && fast && fast->next){
388 slow = slow->next;
389 fast = fast->next->next;
390 }
391 return slow->data;
392 }
393 public:
399 void push_front(T&& data){ //forwadding reference
400 if(tail == head){
401 Node* new_node = _create_node(data);
402 head->next = tail = new_node;
403 size++;
404 }else{
405 Node* new_node = _create_node(data);
406 new_node->next = head->next;
407 head->next = new_node;
408 size++;
409 }
410 }
411 void push_front(const T& data){
412 if(tail == head){
413 Node* new_node = _create_node(data);
414 head->next = tail = new_node;
415 size++;
416 }else{
417 Node* new_node = _create_node(data);
418 new_node->next = head->next;
419 head->next = new_node;
420 size++;
421 }
422
423 }
424
429 void pop_front(){
430 if(tail == head){
431 return;
432 }
433 Node* temp = head->next;
434 head->next = temp->next;
435 if(temp == tail){
436 tail = head;
437 }
438 _destroy_node(temp);
439 size--;
440
441 }
442 public:
447 void push_back(const T& value){
448 if(!head->next){
449 head->next = tail = _create_node(value);
450 size++;
451 }else{
452 tail->next = _create_node(value);
453 tail = tail->next;
454 size++;
455 }
456 }
457 void push_back(T&& value){
458 if(!head->next){
459 head->next = tail = _create_node(value);
460 size++;
461 }else{
462 tail->next = _create_node(value);
463 tail = tail->next;
464 size++;
465 }
466 }
467
471 void pop_back(){
472 if(!head->next){//is_empty
473 return;
474 }else if(!head->next->next){
475 Node* temp = tail;
476 tail = head;
477 tail->next = nullptr;
478 size--;
479 _destroy_node(temp);
480 }else{
481 Node* curr = head->next;
482 while(curr->next->next != nullptr){
483 curr = curr->next;
484 }
485 Node* temp = curr->next;
486 tail = curr;
487 tail->next = nullptr;
488 size--;
489 _destroy_node(temp);
490 }
491 }
492 public:
540 void insert_after(Iterator iter_position,T&& val){
541 Node* curr = iter_position.get_raw();
542 Node* new_node = _create_node(val);
543 new_node->next = curr->next;
544 curr->next = new_node;
545 if(curr == tail){ //jika posisi curr sama dengan tail
546 tail = new_node;
547 }
548 size++; //update size
549 }
550 void insert_after(Iterator iter_position,const T& val){
551 Node* curr = iter_position.get_raw();
552 Node* new_node = _create_node(val);
553 new_node->next = curr->next;
554 curr->next = new_node;
555 if(curr == tail){
556 tail = new_node; //update tail
557 }
558 size++; //increment size
559 }
560 void insert_after(Iterator Iterator_position,int n,T&& val){
561 Node* curr = Iterator_position.get_raw();
562 if(n < 1){
563 return;
564 }
565 if(n == 1){
566 Node* new_node = _create_node(val);
567 new_node->next = curr->next;
568 curr->next = new_node;
569 if(curr == tail){
570 tail = new_node;
571 }
572 }else{
573 Node* new_node = _create_node(val);
574 Node* n_tail = new_node;
575 for(int i = 0;i < n - 1;i++){
576 Node* baru = _create_node(val);
577 n_tail->next = baru;
578 n_tail = baru;
579 }
580 n_tail->next = curr->next;
581 curr->next = new_node;
582 if(curr == tail){
583 tail = n_tail; //karena n_tail menunju node terakhir saat insertion
584 }
585 }
586 }
587 void insert_after(Iterator Iterator_position,int n,const T& val){
588 Node* curr = Iterator_position.get_raw();
589 if(n < 1){
590 return;
591 }
592 if(n == 1){
593 Node* new_node = _create_node(val);
594 new_node->next = curr->next;
595 curr->next = new_node;
596 if(curr == tail){
597 tail = new_node;
598 }
599 }else{
600 Node* new_node = _create_node(val);
601 Node* n_tail = new_node;
602 for(int i = 0;i < n - 1;i++){
603 Node* baru = _create_node(val);
604 n_tail->next = baru;
605 n_tail = baru;
606 }
607 n_tail->next = curr->next;
608 curr->next = new_node;
609 if(curr == tail){
610 tail = n_tail;
611 }
612 }
613 }
614 template<std::input_iterator It>
615 requires (!std::same_as<It,Iterator>)
616 void insert_after(Iterator iter_position,It itr1,It itr2){
617 Node* curr = iter_position.get_raw();
618 Node* new_node = _create_node(*itr1);
619 size++;
620 Node* n_tail = new_node;
621 ++itr1;
622 while(itr1 != itr2){
623 Node* n_node = _create_node(*itr1); //deferencing itr1
624 ++itr1; //increment iterator itr1
625 n_tail->next = n_node;
626 n_tail = n_node;
627 size++;
628 }
629 n_tail->next = curr->next;
630 curr->next = new_node;
631 if(curr == tail){
632 tail = n_tail;
633 }
634 }
635 void insert_after(const Iterator iter_position,Iterator listBegin,const Iterator listEnd){
636 Node* curr = iter_position.get_raw();
637 Node* new_head = listBegin.get_raw();
638 Node* end = listEnd.get_raw();
639 Node* new_node = _create_node(new_head->data);
640 size++;
641 Node* n_tail = new_node;
642 new_head = new_head->next;
643 while(new_head != end){
644 Node* n_node = _create_node(new_head->data);
645 n_tail->next = n_node;
646 n_tail = n_node;
647 new_head = new_head->next;
648 size++;
649 }
650 n_tail->next = curr->next;
651 curr->next = new_node;
652 if(curr == tail){
653 tail = new_node;
654 }
655 }
656 public://overload erase after
657 void erase_after(const Iterator iter_position){
658 Node* curr = iter_position.get_raw();
659 if(!curr->next){//tidak ada node setelah posisi iterator
660 return; //return
661 }
662 if(curr->next == tail){ //jika node selanjutnya tail
663 Node* temp = curr->next;
664 tail = curr; // tail sekarang curr
665 _destroy_node(temp);
666 size--;
667 }else{ //
668 Node* temp = curr->next;
669 curr->next = temp->next;
670 size--;
671 _destroy_node(temp);
672 }
673 }
674 void erase_after(const Iterator pos_begin,const Iterator pos_end){
675 Node* first = pos_begin.get_raw();
676 Node* fst = pos_begin.get_raw();
677 Node* curr = first->next;
678 Node* last = pos_end.get_raw();
679 // curr = curr->next;
680 while(curr != last){
681 if(curr == tail){
682 Node* temp = curr;
683 tail = fst;
684 curr = curr->next;
685 _destroy_node(temp);
686 size--;
687 }else{
688 Node* temp = curr;
689 curr = curr->next;
690 _destroy_node(temp);
691 size--;
692 }
693 }
694 first->next = last;
695 if(last == nullptr){
696 tail = first;
697 }
698 }
699
700 public: //reverse method
701 void reverse(){
702 Node* prev = nullptr;
703 Node* curr = head->next;
704 while(curr != nullptr){
705 Node* next = curr->next;
706 curr->next = next;
707 prev = curr;
708 curr = next;
709 }
710 head->next = prev;
711 }
712 public:
723 void assign(std::size_t n,const T& value){
724 clear();
725 Node* curr = head;
726 for(std::size_t i = 0;i < n;i++){
727 curr->next = _create_node(value);
728 curr = curr->next;
729 size++;
730 }
731 }
732 void assign(std::size_t n,T&& value){
733 clear();
734 Node* curr = head;
735 for(std::size_t i = 0;i < n;i++){
736 curr->next = _create_node(value);
737 curr = curr->next;
738 size++;
739 }
740 }
741 void assign(std::initializer_list<T> arr){
742 clear();
743 head = _create_node(T{});
744 head->next = nullptr;
745 Node** curr = &head->next;
746 //size++;
747 for(const T& value: arr){
748 *curr = _create_node(value); //curr = new Node
749 curr = &((*curr)->next); //curr = curr->next
750 size++;
751 }
752 }
753 template<typename It>
754 requires my_input_iterator<It>
755 void assign(It itr1,It itr2){
756 clear();
757 Node* curr = head;
758 while(itr1 != itr2){
759 curr->next = _create_node(*itr1);//deferencing itr1
760 curr = curr->next;
761 size++;
762 ++itr1;
763 }
764 }
765 public: //slice after
781 void splice_after(const Iterator pos,forward_lists& others,const Iterator It){
782 Node* src = It.get_raw();
783 Node* moved = src->next;
784 src->next = moved->next; //src->next = src->next->next
785
786 Node* dest = pos.get_raw();
787 moved->next = dest->next; //hubungkan ke list tujuan
788 dest->next = moved;
789 others.size--;
790 size++;
791 }
792 void splice_after(const Iterator pos,forward_lists&& others,const Iterator It){
793 Node* src = It.get_raw();
794 Node* moved = src->next;
795 src->next = moved->next; //src->next = src->next->next
796
797 Node* dest = pos.get_raw();
798 moved->next = dest->next; //hubungkan ke list tujuan
799 dest->next = moved;
800 others.size--;
801 size++;
802 }
803 void splice_after(const Iterator pos,forward_lists& others){
804 if(this == &others){
805 return;
806 }
807 Node* src = pos.get_raw();//pos object saat ini
808 Node* begin = others.head->next ; //begin object lain
809 Node* end = others.tail; //end object lain
810
811 end->next = src->next;
812 src->next = begin;
813 //update tail
814 if(src == tail){
815 tail = end;
816 }
817 //update size
818 size += others.size;
819 //kosong object lain
820 others.head->next = nullptr; //harus menunjuk nullptr
821 others.tail = others.head;//reset tail,tail menunjuk head(dummy node)
822 others.size = 0;
823 }
824 void splice_after(const Iterator pos,forward_lists&& others){ //global reference
825 if(this == &others){
826 return;
827 }
828 Node* src = pos.get_raw();//pos object saat ini
829 Node* begin = others.head->next ; //begin object lain
830 Node* end = others.tail; //end object lain
831 end->next = src->next;
832 src->next = begin;
833 //update tail
834 if(src == tail){
835 tail = end;
836 }
837 //update size
838 size += others.size;
839 //kosong object lain
840 others.head->next = nullptr; //harus menunjuk nullptr
841 others.tail = others.head;//reset tail,tail menunjuk head(dummy node)
842 others.size = 0;
843 }
844 void splice_after(const Iterator pos,forward_lists& others,const Iterator first,const Iterator last){
845 //relingking dari range (first,last)
846 Node* curr = pos.get_raw();
847 Node* other_begin = first.get_raw()->next;
848 Node* other_end = last.get_raw();
849 Node* after_node = curr->next; //simpan first this
850 if(other_begin == other_end){
851 return; //nullptr
852 }
853 //update size,update size sebelum di linking
854 auto moved = (std::distance(first, last)) - 1;
855 size += moved;
856 others.size -= moved;
857 //simpan last_node
858 Node* last_node = other_begin;
859 //cari node sebelum lasr
860 while(last_node->next != other_end){
861 last_node = last_node->next;
862 //loop sampai last_node tepat menunjuk sebelum pos last
863 }
864 //sembungkan ke list tujuan
865 last_node->next = curr->next;
866 curr->next = other_begin;
867 //lingking curr->next with to others_begin
868
869 //update tail
870 if(after_node == tail || other_end == nullptr){
871 tail = last_node;
872 }
873 //relingking object lain
874 first.get_raw()->next = other_end;
875 if(other_end == nullptr){
876 others.tail = first.get_raw();
877 }
878
879 }
880 void splice_after(const Iterator pos,forward_lists&& others,const Iterator first,const Iterator last){
881 //relingking dari range (first,last)
882 Node* curr = pos.get_raw();
883 Node* other_begin = first.get_raw()->next;
884 Node* other_end = last.get_raw();
885 Node* after_node = curr->next;
886 if(other_begin == other_end){
887 return; //nullptr
888 }
889 //update size,update size sebelum di linking
890 auto moved = std::distance(std::next(first),(last));
891 size += moved;
892 Node* last_node = other_begin;
893 others.size -= moved;
894 //cari node sebelum lasr
895 while(last_node->next != other_end){
896 last_node = last_node->next;
897 //loop sampai last_node tepat menunjuk sebelum pos last
898 }
899 //sembungkan ke list tujuan
900 last_node->next = curr->next;
901 curr->next = other_begin;
902 //lingking curr->next with to others_begin
903
904 //update tail
905 Node* new_begin = first.get_raw();
906 if(after_node == tail){
907 tail = last_node;
908 }
909 //relingking object lain
910 first.get_raw()->next = other_end;
911 if(other_end == nullptr){
912 others.tail = first.get_raw();
913 }
914
915 }
916 public:
917 void swap(forward_lists& others)noexcept{
918 if(this == &others){//jika this sama dengan object lain
919 return;
920 }
921 //swap head;
922 Node* tempHead = head;
923 head = others.head;
924 others.head = tempHead;
925 //swap tail
926 Node* tempTail = tail;
927 tail = others.tail;
928 others.tail = tempTail;
929 //swap size
930 int tempSize = size;
931 size = others.size;
932 others.size = tempSize;
933 }
934 void swap(forward_lists&& others)noexcept{
935 if(this == &others){//jika this sama dengan object lain
936 return;
937 }
938 //swap head;
939 Node* tempHead = head;
940 head = others.head;
941 others.head = tempHead;
942 //swap tail
943 Node* tempTail = tail;
944 tail = others.tail;
945 others.tail = tempTail;
946 //swap size
947 int tempSize = size;
948 size = others.size;
949 others.size = tempSize;
950 }
951 private: //helper sort
952 Node* merge(Node* left, Node* right) {
953 if (!left) return right;
954 if (!right) return left;
955
956 if (left->data <= right->data) {
957 left->next = merge(left->next, right);
958 return left;
959 } else {
960 right->next = merge(left, right->next);
961 return right;
962 }
963 }
964 // overload with parameter
965 template<typename compare = std::less<T>>
966 Node* merge(Node* left, Node* right,compare comp) {
967 if (!left) return right;
968 if (!right) return left;
969
970 if (comp(left->data, right->data)) {
971 left->next = merge(left->next, right,comp);
972 return left;
973 } else {
974 right->next = merge(left, right->next,comp);
975 return right;
976 }
977 }
979 //mulai dari note pertama
980 Node* slow = head;
981 Node* fast = head->next;
982 while(fast && fast->next){
983 slow = slow->next;
984 fast = fast->next->next;
985 }
986 return slow;
987 }
989 if(!head || !head->next){
990 return head;
991 }
992 Node* middle = getMiddle(head);
993 Node* nextMiddle = middle->next;
994 //putushkan hubungan list
995 middle->next = nullptr;
996 Node* left = helper(head);
997 Node* right = helper(nextMiddle);
998 return merge(left,right);
999 }
1000 template <typename compare>
1001 Node* helper(Node* head,compare comp){
1002 if(!head || !head->next){
1003 return head;
1004 }
1005 Node* middle = getMiddle(head);
1006 Node* nextMiddle = middle->next;
1007 //putushkan hubungan list
1008 middle->next = nullptr;
1009 Node* left = helper(head,comp);
1010 Node* right = helper(nextMiddle,comp);
1011 return merge(left,right,comp);
1012 }
1013 public:
1014 void sort(){
1015 head->next = helper(head->next);
1016 Node* curr = head;
1017 while(curr && curr->next){
1018 curr = curr->next;
1019 }
1020 tail = curr;
1021 }
1022 template <typename Compare = std::less<T>>
1023 void sort(Compare comp = Compare{}) {
1024 head->next = helper(head->next, comp);
1025
1026 // update tail sekali
1027 Node* curr = head;
1028 while (curr && curr->next) {
1029 curr = curr->next;
1030 }
1031 tail = curr;
1032 }
1033 public:
1034 void merge(forward_lists& others){
1035 if(this == &others){
1036 return;
1037 }
1038 Node dummy(T{});
1039 Node* temp = &dummy;
1040 temp->next = nullptr;
1041 Node* curr = head->next;
1042 Node* pos = others.head->next;
1043 while(curr && pos){
1044 if(curr->data <= pos->data){
1045 temp->next = curr;
1046 curr = curr->next;
1047 }else{
1048 temp->next = pos;
1049 pos = pos->next;
1050 // temp = temp->next;
1051 }
1052 temp = temp->next;
1053 }
1054 //update tail
1055 if(curr != nullptr){
1056 temp->next = curr;
1057 // tail = this->tail;
1058 }else if(pos != nullptr){
1059 temp->next = pos;
1060 tail = others.tail;
1061 }else{
1062 tail = temp;
1063 }
1064 //update size
1065 size += others.size;
1066 others.size = 0;
1067 //kosongkan lama
1068 others.head->next = nullptr;
1069 others.tail = head;
1070 //update head
1071 head->next = dummy.next;
1072 }
1073 void merge(forward_lists&& others){
1074 if(this == &others){
1075 return;
1076 }
1077 Node dummy(T{});
1078 Node* temp = &dummy;
1079 temp->next = nullptr;
1080 Node* curr = head->next;
1081 Node* pos = others.head->next;
1082 while(curr && pos){
1083 if(curr->data <= pos->data){
1084 temp->next = curr;
1085 curr = curr->next;
1086 }else{
1087 temp->next = pos;
1088 pos = pos->next;
1089 // temp = temp->next;
1090 }
1091 temp = temp->next;
1092 }
1093 //update tail
1094 if(curr != nullptr){
1095 temp->next = curr;
1096 // tail = this->tail;
1097 }else if(pos != nullptr){
1098 temp->next = pos;
1099 tail = others.tail;
1100 }else{
1101 tail = temp;
1102 }
1103 //update size
1104 size += others.size;
1105 others.size = 0;
1106 //kosongkan lama
1107 others.head->next = nullptr;
1108 others.tail = head;
1109 //update head
1110 head->next = dummy.next;
1111 }
1112 template <typename compare = std::less<T>>
1113 void merge(forward_lists& others,compare comp = compare{}){
1114 if(this == &others){
1115 return;
1116 }
1117 Node dummy(T{});
1118 Node* temp = &dummy;
1119 temp->next = nullptr;
1120 Node* curr = head->next;
1121 Node* pos = others.head->next;
1122 while(curr && pos){
1123 if(comp(curr->data, pos->data)){
1124 temp->next = curr;
1125 curr = curr->next;
1126 }else{
1127 temp->next = pos;
1128 pos = pos->next;
1129 // temp = temp->next;
1130 }
1131 temp = temp->next;
1132 }
1133 //update tail
1134 if(curr != nullptr){
1135 temp->next = curr;
1136 // tail = this->tail;
1137 }else if(pos != nullptr){
1138 temp->next = pos;
1139 tail = others.tail;
1140 }else{
1141 tail = temp;
1142 }
1143 //update size
1144 size += others.size;
1145 others.size = 0;
1146 //kosongkan lama
1147 others.head->next = nullptr;
1148 others.tail = head;
1149 //update head
1150 head->next = dummy.next;
1151 }
1152 template <typename compare = std::less<T>>
1153 void merge(forward_lists&& others,compare comp = compare{}){
1154 if(this == &others){
1155 return;
1156 }
1157 Node dummy(T{});
1158 Node* temp = &dummy;
1159 temp->next = nullptr;
1160 Node* curr = head->next;
1161 Node* pos = others.head->next;
1162 while(curr && pos){
1163 if(comp(curr->data, pos->data)){
1164 temp->next = curr;
1165 curr = curr->next;
1166 }else{
1167 temp->next = pos;
1168 pos = pos->next;
1169 // temp = temp->next;
1170 }
1171 temp = temp->next;
1172 }
1173 //update tail
1174 if(curr != nullptr){
1175 temp->next = curr;
1176 // tail = this->tail;
1177 }else if(pos != nullptr){
1178 temp->next = pos;
1179 tail = others.tail;
1180 }else{
1181 tail = temp;
1182 }
1183 //update size
1184 size += others.size;
1185 others.size = 0;
1186 //kosongkan lama
1187 others.head->next = nullptr;
1188 others.tail = head;
1189 //update head
1190 head->next = dummy.next;
1191 }
1192 public:
1194 if(this == &others){
1195 return;
1196 }
1197 if(head->next->data <= others.head->next->data){
1198 //sambung mulai tail dengan head.tail
1199 tail->next = others.head->next;
1200 //update tail
1201 tail = others.tail;
1202 //update size
1203 size += others.size;
1204 others.head->next = nullptr;
1205 others.tail = others.head;
1206 }else{
1207 others.tail->next = head->next;
1208 //update head pada this
1209 head->next = others.head->next;
1210 //update size
1211 size += others.size;
1212 }
1213
1214 }
1216 if(this == &others){
1217 return;
1218 }
1219 if(head->next->data <= others.head->next->data){
1220 //sambung tail
1221 tail->next = others->head->next;
1222 //update tail
1223 tail = others.tail;
1224 //update size
1225 size += others.size;
1226 }else{
1227 //sambung others tail ke node setelah dummy
1228 others.tail->next = head->next;
1229 //sambung node setelah du
1230 head->next = others.head->next;
1231 //update size
1232 size += others.size;
1233 }
1234 }
1235 public:
1245 void resize(std::size_t count){
1246 if(count == size){
1247 return;
1248 }else if(count > size){
1249 while(size < count){
1250 push_back(0);
1251 size++;
1252 }
1253 }else{
1254 while(size > count){
1255 pop_back();
1256 size--;
1257 }
1258 }
1259 }
1260 void resize(std::size_t count,const T& value){
1261 if(count == size){
1262 return;
1263 }else if(count > size){
1264 while(size < count){
1265 push_back(value);
1266 size++;
1267 }
1268 }else{
1269 while(size > count){
1270 pop_back();
1271 size--;
1272 }
1273 }
1274
1275 }
1276 public:
1277 //time complexity O(n),Space Complexity O(n)
1279 std::unordered_set<T>seen;
1280 Node* curr = head;
1281 Node* fast = head->next;
1282 if(!fast){
1283 return;//jika list kosong
1284 }
1285 while(fast != nullptr){
1286 if(seen.find(fast->data) != seen.end()){
1287 Node* temp = fast;
1288 Node* _next = fast->next;
1289 //relinking curr dengan fast->next
1290 curr->next = _next;
1291 _destroy_node(temp);
1292 if(_next != nullptr){
1293 fast = _next;
1294 // curr = curr->next;//melompat 2 kali
1295 }else{
1296 fast = nullptr;
1297 }
1298 }else{
1299 seen.insert(fast->data);
1300 curr = curr->next; //maju sekali jika tidak ada di set
1301 fast = fast->next;
1302 }
1303 }
1304 }
1305 void uniqe(){
1306 Node* curr = head;
1307 Node* fast = head->next;
1308 if(fast == nullptr){
1309 return;
1310 }
1311 while(fast && fast->next){
1312 if(fast->data == fast->next->data){
1313 Node* temp = fast;
1314 Node* _next = fast->next;
1315 curr->next = _next;
1316 _destroy_node(temp);
1317 fast = _next;
1318 }else{
1319 curr = curr->next;
1320 fast = fast->next;
1321 }
1322 }
1323 }
1324 public:
1325 template<std::ranges::input_range R>
1326 void assign_range(R&& rg){
1327 clear();
1328 size = 0;
1329 Node* curr = head;
1330 for(auto&& elem: rg){
1331 if(!curr){
1332 size++;
1333 curr->next = tail = _create_node(elem);
1334 }else{
1335 Node* new_node = _create_node(elem);
1336 curr->next = new_node;
1337 curr = curr->next; //majukan curr
1338 tail = curr; //tail menunjuk currr
1339 size++;
1340 }
1341 }
1342 }
1343 // template<typename T>
1344 void assign_range(std::initializer_list<T> arr){
1345 clear();
1346 size = 0;
1347 Node* curr = head;
1348 for(const T& x: arr){
1349 if(!curr){
1350 curr->next = tail = _create_node(x);
1351 size++;
1352 }else{
1353 curr->next = _create_node(x);
1354 curr = curr->next;
1355 tail = curr;
1356 size++;
1357 }
1358 }
1359 }
1360 public:
1370 void remove(const T& value){
1371 if(!head->next){ //list is empty
1372 return;
1373 }
1374 Node* curr = head;
1375 while(curr->next != nullptr){
1376 if(curr->next->data == value){
1377 Node* _next = curr->next;
1378 if(_next == tail){
1379 curr->next = nullptr;
1380 tail = curr;
1381 tail->next = nullptr;
1382 }else{
1383 curr->next = _next->next;
1384 }
1385 size--;
1386 _destroy_node(_next);
1387 }else{
1388 curr = curr->next;
1389 }
1390 }
1391 if(!head->next){
1392 tail = head;
1393 size = 0;
1394 }
1395 }
1396
1405 void remove(const std::size_t pos){
1406 if(!head->next){
1407 return;
1408 }
1409 if(pos >= static_cast<std::size_t>(size)){
1410 return;
1411 }
1412
1413 //- 1 1 1 2 2
1414 Node* prev = head;
1415 Node* curr = head->next;
1416 static_assert(std::is_same_v<decltype(curr), Node*>);
1417 static_assert(std::is_same_v<decltype(tail), Node*>);
1418
1419 for(std::size_t i = 0;i < pos;i++){
1420 prev = curr;
1421 curr = curr->next;
1422 }
1423 //sekarang curr menunjuk pos
1424 if(curr == tail){
1425 head->next = nullptr;
1426 curr = nullptr;
1427 tail = head;
1428 }else{
1429 prev->next = curr->next;
1430 }
1431 size--;
1432 _destroy_node(curr);
1433 if(!head->next){
1434 tail = head;
1435 size = 0;
1436 }
1437 }
1438 std::size_t remove_count(const T& value){
1439 if(!head->next){ //list is empty
1440 return 0;
1441 }
1442 int cnt = 0;
1443 Node* curr = head;
1444 while(curr->next != nullptr){
1445 if(curr->next->data == value){
1446 Node* _next = curr->next;
1447 if(_next == tail){
1448 curr->next = nullptr;
1449 tail = curr;
1450 tail->next = nullptr;
1451 }else{
1452 curr->next = _next->next;
1453 }
1454 size--;
1455 cnt++;
1456 _destroy_node(_next);
1457 }else{
1458 curr = curr->next;
1459 }
1460 }
1461 if(!head->next){
1462 tail = head;
1463 size = 0;
1464 }
1465 return cnt;
1466 }
1467 template <class UnaryPred>
1468 requires(std::predicate<UnaryPred&, const T&>)
1469 void remove_if(UnaryPred p){
1470 if(!head->next){
1471 return;
1472 }
1473 Node* curr = head->next;
1474 Node* prev = head;
1475 while(curr != nullptr){
1476 if(p(curr->data)){
1477 Node* _next = curr->next;
1478 // Node* temp = curr;
1479 //relink pada next
1480 prev->next = _next;
1481 if(_next == nullptr){//curr == tail
1482 tail = prev;
1483 }
1484 //majukan curr
1485 _destroy_node(curr);
1486 size--;
1487 curr = _next;
1488 }else{
1489 prev = curr;
1490 curr = curr->next;
1491 }
1492 }
1493 if(!head->next){ //jika terhapus semua
1494 tail = head;
1495 head->next = nullptr;
1496 size = 0;
1497 }
1498 }
1499 template <class UnaryPred>
1500 requires(std::predicate<UnaryPred&,const T&>)
1501 std::size_t remove_if_count(UnaryPred p){
1502 if(!head->next){
1503 return 0;
1504 }
1505 std::size_t count = 0;
1506 Node* curr = head->next;
1507 Node* prev = head;
1508 while(curr != nullptr){
1509 if(p(curr->data)){
1510 Node* _next = curr->next;
1511 //linking prev
1512 prev->next = _next;
1513 //check _next;
1514 if(_next == nullptr){
1515 tail = prev;
1516
1517 }
1518 _destroy_node(curr);
1519 size--;
1520 curr = _next;
1521 count++;//increment count
1522 }else{
1523 prev = curr;
1524 curr = curr->next;
1525 }
1526 }
1527 return count;
1528 }
1529 public:
1536 while(begin != end){
1537 std::cout << *begin << " ";
1538 ++begin;
1539 }
1540 std::cout << std::endl;
1541 }
1542
1547 public:
1548 template <std::ranges::input_range R>
1549 void insert_range_after(const Iterator& pos,R&& r){
1550 Node* curr = pos.get_raw();
1551 if(is_empty()){
1552 Node* _next = curr->next; //nullptr
1553 for(auto&& x: r){
1554 curr->next = _create_node(x);
1555 curr = curr->next;
1556 size++;
1557 }
1558 //linking node terakhir r ke _next
1559 curr->next = _next;
1560 tail = curr;
1561 }else{
1562 Node* _next = curr->next;
1563 for(auto&& x: r){
1564 curr->next = _create_node(x);
1565 curr = curr->next;
1566 size++;
1567 }
1568 //linking node terakhir r ke _next
1569 curr->next = _next;
1570 }
1571 }
1572 public:
1573 template<std::ranges::input_range R>
1574 void prepend_range(R&& r){
1575 if(is_empty()){
1576 Node* curr = head;
1577 Node* _next = head->next; //nullptr
1578 for(auto&& x: r){
1579 curr->next = _create_node(x);
1580 curr = curr->next;
1581 size++;
1582 }
1583 curr->next = _next;
1584 tail = curr;
1585 }else{
1586 Node* curr = head;
1587 Node* _next = head->next;
1588 for(auto&& x: r){
1589 curr->next = _create_node(x);
1590 curr = curr->next;
1591 size++;
1592 }
1593 curr->next = _next;
1594 }
1595 }
1596 public:
1597 template <class ... Args>
1598 void emplace_front(Args&&... args){
1599 Node* new_node = _create_node(std::forward<Args>(args)...);
1600 //linking head baru ke head lama
1601 if(!head->next){
1602 tail = new_node;
1603 }
1604 new_node->next = head->next;
1605 //update head;
1606 head->next = new_node;
1607 //update size;
1608 size++;
1609 }
1610 template <class ... Args>
1611 void emplace_after(Iterator pos,Args&&... args){
1612 Node* curr = pos.get_raw();
1613 if(!curr){
1614 return;
1615 }
1616 Node* _next = curr->next;
1617 Node* new_node = _create_node(std::forward<Args>(args)...);
1618
1619 //linking
1620 new_node->next = _next;
1621 curr->next = new_node;
1622 //emplace pada saat list kosong
1623 if(curr == tail){
1624 tail = new_node;
1625 }
1626 size++;
1627 }
1628 template<class... Args>
1629 void emplace_back(Args&&... args){
1630 Node* new_node = _create_node(std::forward<Args>(args)...);
1631 tail->next = new_node;
1632 tail = new_node;
1633 //update size
1634 size++;
1635 }
1636 public:
1637 void clear(){
1638 Node* curr = head->next; // mulai dari setelah dummy
1639 while(curr != nullptr){
1640 Node* next = curr->next; //simpan curr->next
1641 _destroy_node(curr); //hancurkan curr
1642 curr = next;//curr menunjuk next
1643 }
1644 head->next = nullptr; // dummy menunjuk ke kosong
1645 tail = head; // tail kembali ke dummy
1646 size = 0;
1647 }
1648};
1649#endif
Definition forward_list.hpp:221
bool operator!=(const Iterator &others) const
Definition forward_list.hpp:285
std::forward_iterator_tag iterator_category
iterator category iterator category adalah label yang menjelaskan kemampuan sebuah
Definition forward_list.hpp:248
T & operator*()
Definition forward_list.hpp:264
Iterator & operator->()
Definition forward_list.hpp:277
T * pointer
Definition forward_list.hpp:251
T & reference
Definition forward_list.hpp:252
Node * node
Definition forward_list.hpp:223
Iterator & operator++()
Definition forward_list.hpp:273
Iterator(Node *n)
Definition forward_list.hpp:253
bool operator==(const Iterator &others) const
Definition forward_list.hpp:288
T value_type
Definition forward_list.hpp:249
std::ptrdiff_t difference_type
Definition forward_list.hpp:250
pointer operator->() const
Definition forward_list.hpp:270
reference operator*() const
Definition forward_list.hpp:267
friend std::ostream & operator<<(std::ostream &os, const Iterator &it)
Definition forward_list.hpp:256
Iterator operator++(int)
Definition forward_list.hpp:280
Node * get_raw() const
Definition forward_list.hpp:291
forward_lists(It begin, It end)
constructor range,adalah constructor yang menginialisasi nilai dari sebuah container dengan element d...
Definition forward_list.hpp:106
Allocator get_allocator() const noexcept
Definition forward_list.hpp:369
bool check_cycle() const noexcept
Definition forward_list.hpp:372
Node * helper(Node *head)
Definition forward_list.hpp:988
void clear()
Definition forward_list.hpp:1637
Iterator end()
iterator yang menunjuk pointer setelah node terakhir(tail)
Definition forward_list.hpp:311
void push_front(T &&data)
method untuk insertion val pada pos front
Definition forward_list.hpp:399
void merge(forward_lists &others, compare comp=compare{})
Definition forward_list.hpp:1113
void sort()
Definition forward_list.hpp:1014
void pop_front()
method untuk deletion val pada pos front
Definition forward_list.hpp:429
node_allocator_type alloc
Definition forward_list.hpp:54
void uniqe()
Definition forward_list.hpp:1305
~forward_lists()
destructor
Definition forward_list.hpp:217
Node * tail
Definition forward_list.hpp:56
void emplace_front(Args &&... args)
Definition forward_list.hpp:1598
void splice_after(const Iterator pos, forward_lists &others, const Iterator first, const Iterator last)
Definition forward_list.hpp:844
typename std::allocator_traits< Allocator >::template rebind_alloc< Node > node_allocator_type
Definition forward_list.hpp:51
void resize(std::size_t count, const T &value)
Definition forward_list.hpp:1260
void assign(It itr1, It itr2)
Definition forward_list.hpp:755
void splice_after(const Iterator pos, forward_lists &others, const Iterator It)
slice after method untuk memindahkan node dari satu list ke list lain tanpa menyalin data,...
Definition forward_list.hpp:781
void push_front(const T &data)
Definition forward_list.hpp:411
std::size_t remove_if_count(UnaryPred p)
Definition forward_list.hpp:1501
Iterator cbefore_begin() const
Definition forward_list.hpp:320
void push_back(T &&value)
Definition forward_list.hpp:457
T back() const noexcept
Definition forward_list.hpp:366
Node * merge(Node *left, Node *right)
Definition forward_list.hpp:952
void assign(std::initializer_list< T > arr)
Definition forward_list.hpp:741
void emplace_back(Args &&... args)
Definition forward_list.hpp:1629
void assign(std::size_t n, T &&value)
Definition forward_list.hpp:732
void insert_after(Iterator iter_position, const T &val)
Definition forward_list.hpp:550
Node * merge(Node *left, Node *right, compare comp)
Definition forward_list.hpp:966
T front()
method getter yang mengembalikan nilai node pada pos front
Definition forward_list.hpp:328
Node * getMiddle(Node *head)
Definition forward_list.hpp:978
void print_all(Iterator begin, Iterator end)
method untuk print semua node list
Definition forward_list.hpp:1535
void insert_after(Iterator Iterator_position, int n, const T &val)
Definition forward_list.hpp:587
void splice_after(const Iterator pos, forward_lists &&others)
Definition forward_list.hpp:824
void push_back(const T &value)
adalah method untuk melakukan insertion dari posisi belakang(tail)
Definition forward_list.hpp:447
forward_lists(std::initializer_list< T > arr)
initializer list constructor
Definition forward_list.hpp:125
void insert_after(Iterator Iterator_position, int n, T &&val)
Definition forward_list.hpp:560
forward_lists & operator=(const forward_lists &others)
Definition forward_list.hpp:157
void reverse()
Definition forward_list.hpp:701
void merge(forward_lists &&others)
Definition forward_list.hpp:1073
Node * head
Definition forward_list.hpp:55
void _destroy_node(Node *n) noexcept
Definition forward_list.hpp:86
Node * _create_node(const T &value)
Allocator explanation Allocator adalah abstraksi cara mengelola memory pada container alih2 melakukan...
Definition forward_list.hpp:74
void merge_sort(forward_lists &&others)
Definition forward_list.hpp:1215
std::size_t remove_count(const T &value)
Definition forward_list.hpp:1438
void erase_after(const Iterator iter_position)
Definition forward_list.hpp:657
void erase_after(const Iterator pos_begin, const Iterator pos_end)
Definition forward_list.hpp:674
void merge(forward_lists &others)
Definition forward_list.hpp:1034
Iterator before_begin()
iterator yang menunjuk dummy node yaitu head
Definition forward_list.hpp:299
void splice_after(const Iterator pos, forward_lists &&others, const Iterator It)
Definition forward_list.hpp:792
void assign_range(R &&rg)
Definition forward_list.hpp:1326
std::allocator_traits< node_allocator_type > node_traits
Definition forward_list.hpp:53
void merge_sort(forward_lists &others)
Definition forward_list.hpp:1193
void remove(const std::size_t pos)
method overload remove,untuk menghapus node pada posisi pos
Definition forward_list.hpp:1405
forward_lists(const Allocator &a)
Definition forward_list.hpp:95
void sort(Compare comp=Compare{})
Definition forward_list.hpp:1023
void splice_after(const Iterator pos, forward_lists &&others, const Iterator first, const Iterator last)
Definition forward_list.hpp:880
void prepend_range(R &&r)
Definition forward_list.hpp:1574
void insert_after(Iterator iter_position, It itr1, It itr2)
Definition forward_list.hpp:616
void insert_after(const Iterator iter_position, Iterator listBegin, const Iterator listEnd)
Definition forward_list.hpp:635
int size
Definition forward_list.hpp:57
int get_size()
method getter yang mengembalilkan jumlah element saat ini
Definition forward_list.hpp:335
std::size_t max_size() const noexcept
mengembalikan jumlah maksimum yang dapat di tampung list
Definition forward_list.hpp:363
forward_lists(forward_lists &&others) noexcept
move constructor dipakai ketika ingin memindahkan node pada list a ke list b
Definition forward_list.hpp:185
Iterator begin()
iterator yang menunjuk node pada element pertama pada list
Definition forward_list.hpp:305
void pop_back()
pop_back adalah method untuk deletion node di posisi tail
Definition forward_list.hpp:471
void assign_range(std::initializer_list< T > arr)
Definition forward_list.hpp:1344
T get_middle() const noexcept
Definition forward_list.hpp:384
void insert_after(Iterator iter_position, T &&val)
Menyisipkan elemen setelah posisi iterator tertentu.
Definition forward_list.hpp:540
void remove_if(UnaryPred p)
Definition forward_list.hpp:1469
forward_lists(const forward_lists &others)
Definition forward_list.hpp:141
bool is_empty()
method getter yang mengembalilkan true jika list empty,sebalik false jika tidak kosong
Definition forward_list.hpp:342
forward_lists & operator=(forward_lists &&others) noexcept
move assignment constructor
Definition forward_list.hpp:198
void swap(forward_lists &others) noexcept
Definition forward_list.hpp:917
Iterator cend() const
Definition forward_list.hpp:317
void resize(std::size_t count)
resize adalah method untuk mengubah ukuran sebuah list
Definition forward_list.hpp:1245
void insert_range_after(const Iterator &pos, R &&r)
method untuk menghapus semua node pada head berguna pada destructor
Definition forward_list.hpp:1549
void uniqe_all()
Definition forward_list.hpp:1278
void swap(forward_lists &&others) noexcept
Definition forward_list.hpp:934
forward_lists()
Definition forward_list.hpp:92
void merge(forward_lists &&others, compare comp=compare{})
Definition forward_list.hpp:1153
Iterator cbegin() const
Definition forward_list.hpp:314
void remove(const T &value)
overload remove untuk menghapus node dengan nilai sama dengan parameter value
Definition forward_list.hpp:1370
Node * helper(Node *head, compare comp)
Definition forward_list.hpp:1001
void splice_after(const Iterator pos, forward_lists &others)
Definition forward_list.hpp:803
void emplace_after(Iterator pos, Args &&... args)
Definition forward_list.hpp:1611
void assign(std::size_t n, const T &value)
Method Assign Assign dipakai untuk mereplace list saat ini dengan list baru overload method assign as...
Definition forward_list.hpp:723
Definition forward_list.hpp:38
Definition forward_list.hpp:46
T data
Definition forward_list.hpp:47
Node * next
Definition forward_list.hpp:48