Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_dynDlist.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
43#ifndef TPL_DYNDLIST_H
44#define TPL_DYNDLIST_H
45
46#include <ahFunctional.H>
47#include <ahDry.H>
48#include <ah-dry.H>
49#include <ah-args-ctor.H>
50#include <ahIterator.H>
51#include <ah-iterator.H>
52#include <tpl_dnode.H>
53#include <stdexcept>
54#include <ah-errors.H>
55
56namespace Aleph {
57
114template <typename T = int>
115class DynDlist : public Dnode<T>,
116 public GenericTraverse<DynDlist<T>>,
117 public SpecialCtors<DynDlist<T>, T>,
118 public LocateFunctions<DynDlist<T>, T>,
119 public FunctionalMethods<DynDlist<T>, T>,
120 public GenericItems<DynDlist<T>, T>,
121 public EqualSequenceMethod<DynDlist<T>>,
122 public StlAlephIterator<DynDlist<T>>
123{
124 size_t num_elem = 0;
125
126public:
129
131 using Item_Type = T;
132
134 using Key_Type = T;
135
137 [[nodiscard]] const size_t &size() const noexcept
138 {
139 return num_elem;
140 }
141
142 DynDlist() = default;
143
144 // using CtorBase = SpecialCtors<DynDlist<T>, T>;
145 // using CtorBase::CtorBase;
146
147 // /** Construct a new list with copies of elements of list `l`
148
149 // \param[in] l list to be copied
150 // \throw bad_alloc if there is no enough memory
151 // */
152 // DynDlist(const DynList<T> & l) : Dnode<T>(), CtorBase(l) {}
153
155
165 {
166 while (not this->is_empty())
167 delete this->Dnode<T>::remove_next();
168
169 num_elem = 0;
170 }
171
179 void clear() noexcept { empty(); }
180
182 {
183 empty();
184 }
185
186private:
187 T &_insert(Dnode<T> *p) noexcept
188 {
190 ++num_elem;
191 return p->get_data();
192 }
193
194 T &_append(Dnode<T> *p) noexcept
195 {
197 ++num_elem;
198 return p->get_data();
199 }
200
201public:
208 T &insert(const T &item)
209 {
210 return _insert(new Dnode<T>(item));
211 }
212
219 T &insert(T &&item)
220 {
221 return _insert(new Dnode<T>(std::forward<T>(item)));
222 }
223
230 T &append(const T &item)
231 {
232 return _append(new Dnode<T>(item));
233 }
234
241 T &append(T &&item)
242 {
243 return _append(new Dnode<T>(std::forward<T>(item)));
244 }
245
246private:
247 void _insert(DynDlist<T> &list) noexcept
248 {
249 Dlink::insert_list(&list);
250 num_elem += list.num_elem;
251 list.num_elem = 0;
252
253 assert(list.is_empty());
254 }
255
256 void _append(DynDlist<T> &list) noexcept
257 {
258 Dlink::append_list(&list);
259 num_elem += list.num_elem;
260 list.num_elem = 0;
261
262 assert(list.is_empty());
263 }
264
265public:
270 void insert(const DynDlist &list)
271 {
272 auto l = list; // perform a copy of list
273 _insert(l);
274 }
275
277 void insert(DynDlist &&list) noexcept
278 {
279 _insert(list);
280 }
281
286 void append(const DynDlist &list)
287 {
288 auto l = list; // perform a copy of list
289 _append(l);
290 }
291
293 void append(DynDlist &&list) noexcept
294 {
295 _append(list);
296 }
297
300 {
301 return this->get_next()->get_data();
302 }
303
306 {
307 return this->get_prev()->get_data();
308 }
309
311 T &get_first() const
312 {
313 ah_underflow_error_if(this->is_empty()) << "DynDlist is empty";
314 return get_first_ne();
315 }
316
318 T &get_last() const
319 {
320 ah_underflow_error_if(this->is_empty()) << "DynDlist is empty";
321 return get_last_ne();
322 }
323
329 {
330 Dnode<T> *ptr = this->remove_next();
331 T retVal = ptr->get_data();
332 delete ptr;
333 --num_elem;
334
335 return retVal;
336 }
337
343 {
344 Dnode<T> *ptr = this->remove_prev();
345 T retVal = ptr->get_data();
346 delete ptr;
347 --num_elem;
348
349 return retVal;
350 }
351
358 {
359 ah_underflow_error_if(this->is_empty()) << "DynDlist is empty";
360 return remove_first_ne();
361 }
362
369 {
370 ah_underflow_error_if(this->is_empty()) << "DynDlist is empty";
371 return remove_last_ne();
372 }
373
375 T &put(const T &item)
376 {
377 return append(item);
378 }
379
381 T &put(T &&item)
382 {
383 return append(std::forward<T>(item));
384 }
385
388 {
389 return remove_first();
390 }
391
395 {
396 return get_last();
397 }
398
402 {
403 return get_first();
404 }
405
407 T &push(const T &item)
408 {
409 return insert(item);
410 }
411
413 T &push(T &&item)
414 {
415 return insert(std::forward<T>(item));
416 }
417
420 {
421 return remove_first();
422 }
423
425 T &top() const
426 {
427 return get_first();
428 }
429
443 void remove(T &data) noexcept
444 {
446 p->del();
447 delete p;
448 --num_elem;
449 }
450
452 void erase(T &data) noexcept
453 {
454 remove(data);
455 }
456
459 void swap(DynDlist &l) noexcept
460 {
461 std::swap(num_elem, l.num_elem);
462 this->Dlink::swap(&l);
463 }
464
477 {
479
480 const auto count_nodes = [](const DynDlist &list) noexcept -> size_t
481 {
482 size_t count = 0;
483 for (auto it = list.get_it(); it.has_curr(); it.next_ne())
484 ++count;
485 return count;
486 };
487
488 l.num_elem = count_nodes(l);
489 r.num_elem = count_nodes(r);
490 num_elem = 0;
491 }
492
505 {
506 ah_domain_error_if((not l.is_empty()) or (not r.is_empty())) << "lists are not empty";
507 split_list_ne(l, r);
508 }
509
513 {
514 split_list(l, r);
515 }
516
521 class Iterator : public Dnode<T>::Iterator
522 {
523 DynDlist *list_ptr; // Pointer to list
524 long pos; // Position of the current element in the sequence
525
526 using Base = typename Dnode<T>::Iterator;
527
528 public:
531
533 using Item_Type = T;
534
537 {
538 return pos;
539 }
540
544 {
546 pos++;
547 }
548
551 void next()
552 {
554 pos++;
555 }
556
559 void prev()
560 {
562 pos--;
563 }
564
567 {
569 pos = 0;
570 }
571
578
581 {
582 put_itor_at_the_end(*this);
583 }
584
587 : Base(list), list_ptr(&const_cast<DynDlist &>(list)), pos(0)
588 {
589 // empty
590 }
591
593 { /* empty */
594 }
595
596 Iterator(const Iterator &) = default;
597
598 Iterator &operator=(const Iterator &it) noexcept
599 {
600 if (this == &it)
601 return *this;
603 list_ptr = it.list_ptr;
604 pos = it.pos;
605
606 return *this;
607 }
608
611 T &get_curr() const
612 {
613 return Dnode<T>::Iterator::get_curr()->get_data();
614 }
615
617 {
618 return Dnode<T>::Iterator::get_curr_ne()->get_data();
619 }
620
630 void insert(const T &item)
631 {
632 ah_overflow_error_if(not this->has_curr()) << "DynDlist Iterator has not current";
633
634 Dnode<T>::Iterator::get_curr()->insert(new Dnode<T>(item));
636 }
637
648 void insert(T &&item)
649 {
650 ah_overflow_error_if(not this->has_curr()) << "DynDlist Iterator has not current";
651
652 Dnode<T>::Iterator::get_curr()->insert(new Dnode<T>(std::forward<T>(item)));
654 }
655
665 void append(const T &item)
666 {
667 ah_overflow_error_if(not this->has_curr()) << "DynDlist Iterator has not current";
668
669 Dnode<T>::Iterator::get_curr()->append(new Dnode<T>(item));
671 }
672
683 void append(T &&item)
684 {
685 ah_overflow_error_if(not this->has_curr()) << "DynDlist Iterator has not current";
686
687 Dnode<T>::Iterator::get_curr()->append(new Dnode<T>(std::forward<T>(item)));
689 }
690
707 {
708 ah_overflow_error_if(not this->has_curr()) << "DynDlist Iterator has not current";
709
710 Dnode<T>::Iterator::get_curr()->insert_list(&list);
711 list_ptr->num_elem += list.num_elem;
712 list.num_elem = 0;
713
714 assert(list.is_empty());
715 }
716
733 {
734 ah_overflow_error_if(not this->has_curr()) << "DynDlist Iterator has not current";
735
736 Dnode<T>::Iterator::get_curr()->append_list(&list);
737 list_ptr->num_elem += list.num_elem;
738 list.num_elem = 0;
739
740 assert(list.is_empty());
741 }
742
750 {
751 ah_overflow_error_if(not this->has_curr()) << "DynDlist Iterator has not current";
752
754 T ret_val = ptr->get_data();
756 ptr->del();
757 delete ptr;
759 return ret_val;
760 }
761 };
762
773 {
774 if (this == &list)
775 return *this;
776
777 empty();
778
779 for (Iterator itor(const_cast<DynDlist &>(list)); itor.has_curr(); itor.next_ne())
780 this->append(itor.get_curr());
781
782 return *this;
783 }
784
792 DynDlist(const DynDlist &list) : DynDlist()
793 {
794 assert(this->is_empty());
795
796 for (Iterator itor(const_cast<DynDlist &>(list)); itor.has_curr(); itor.next_ne())
797 this->append(itor.get_curr());
798 }
799
809 {
810 swap(list);
811 }
812
822 {
823 swap(list);
824 return *this;
825 }
826
829 T &operator[](const size_t n) const
830 {
831 auto it = this->get_it();
832 for (size_t i = 0; i < n && it.has_curr(); ++i)
833 it.next_ne();
834
835 ah_out_of_range_error_if(not it.has_curr()) << "DynDlist index out of range";
836
837 return it.get_curr();
838 }
839
841 {
843 return *this;
844 }
845
847 {
848 return reverse();
849 }
850
856 {
858 for (auto it = this->get_it(); it.has_curr(); it.next_ne())
859 ret.insert(it.get_curr());
860 return ret;
861 }
862
864 {
865 return reverse();
866 }
867};
868
869} // end namespace Aleph
870
871#endif /* TPL_DYNDLIST_H */
Variadic constructor macros for containers.
Container traversal and functional operation mixins.
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:579
#define ah_underflow_error_if(C)
Throws std::underflow_error if condition holds.
Definition ah-errors.H:368
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:463
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
STL-compatible iterator adapters for Aleph containers.
DRY (Don't Repeat Yourself) utilities and macros.
#define Special_Ctors(Set_Type, Type)
Generates special constructors for containers.
Definition ahDry.H:113
Functional programming utilities for Aleph-w containers.
Iterator traits and STL-compatible iterator wrappers.
void put_itor_at_the_end(Itor &it) noexcept
Definition aleph.H:54
Iterator on a list of Dnode objects.
Definition tpl_dnode.H:261
Dnode< T > * get_curr_ne() const noexcept
Return the current link guaranteeing no exception. Be careful.
Definition tpl_dnode.H:275
Dnode< T > * get_curr() const
Return a pointer to the current node.
Definition tpl_dnode.H:285
Node belonging to a double circular linked list with header node.
Definition tpl_dnode.H:106
Dnode< T > *& get_next() const noexcept
Return the next node to this
Definition tpl_dnode.H:114
Dnode< T > * remove_next() noexcept
Remove the next node to this; return its address.
Definition tpl_dnode.H:123
T & get_data() noexcept
Return a modifiable reference to the data contained in the node.
Definition tpl_dnode.H:232
Dnode< T > *& get_prev() const noexcept
Return the previous node to this
Definition tpl_dnode.H:117
static Dnode * data_to_node(T &data) noexcept
Given an reference to the data in the node, returns a pointer to the Dnode object that contains it.
Definition tpl_dnode.H:248
Dnode< T > * remove_prev() noexcept
Remove the previous node to this; return its address.
Definition tpl_dnode.H:120
Iterator dynamic list.
void append_list(DynDlist &list)
Move and append all elements of list before the current item of iterator.
T Item_Type
The type of element stored in the container.
typename Dnode< T >::Iterator Base
void next_ne() noexcept
Move the iterator one position forward guaranteeing no exception.
void insert(const T &item)
Insert by copy an item after the current item.
Iterator(const Iterator &)=default
T & get_curr() const
Return the current item; throw overflow_error if there is no current item.
void reset_last() noexcept
Reset the iterator to the last item.
Iterator & operator=(const Iterator &it) noexcept
void end() noexcept
Put the iterator at the end state (where there is no current item)
void prev()
Move the iterator one item backward.
long get_pos() const noexcept
Return the ordinal position of the current item.
void insert(T &&item)
Insert by movement an item after the current item.
T del()
Remove from the list the current node and move the iterator one position forward.
void append(T &&item)
Append by movement an item after the current item.
void insert_list(DynDlist &list)
Move and insert all elements of list after the current item of iterator.
void reset_first() noexcept
Reset the iterator to the first item.
Iterator(const DynDlist< T > &list) noexcept
Initialize the iterator to the first item of list
void append(const T &item)
Append by copy an item before the current item.
void next()
Move the iterator one item forward.
T & get_curr_ne() const noexcept
Dynamic doubly linked list with O(1) size and bidirectional access.
T & get_last() const
Return a modifiable reference to last item in the list.
void insert(DynDlist &&list) noexcept
const size_t & size() const noexcept
Return the number of elements (constant time)
void _insert(DynDlist< T > &list) noexcept
DynDlist & reverse() noexcept
T Key_Type
The type of element that stores the container.
T & front()
If this was treated as a queue, the it returns the most oldlest inserted item.
DynDlist< T > reverse() const
Return a reversed copy of this
DynDlist< T > & operator=(DynDlist &&list) noexcept
Assignment by moving.
T & push(T &&item)
T & get_first_ne() const noexcept
Return a modifiable reference to first item in the list.
T & put(T &&item)
T & operator[](const size_t n) const
Return a modifiable reference to the i-th item of the list.
void split_list(DynDlist &l, DynDlist &r)
Split the list in two.
void swap(DynDlist &l) noexcept
Swap in constant time all the items of this with all the items of l (very fast!)
T Item_Type
The type of element that stores the container.
T & push(const T &item)
T remove_last()
Remove the last item of the list; return a copy of removed item.
DynDlist()=default
DynDlist(DynDlist< T > &&list) noexcept
Move constructor; all items of list are moved.
void remove(T &data) noexcept
Assuming that data is a reference to the item in the list, it removes the item.
void insert(const DynDlist &list)
Insert all the elements of list before this.
T & put(const T &item)
void empty() noexcept
@brief Empties the container.
T & append(const T &item)
Append a copied item at the end of the list.
T & append(T &&item)
Append a moved item at the end of the list.
DynDlist & rev() noexcept
T & rear()
If this was treated as a queue, the it returns the most recently inserted item.
void split(DynDlist &l, DynDlist &r)
This is an overloaded member function, provided for convenience. It differs from the above function o...
DynDlist< T > rev() const
T & get_first() const
Return a modifiable reference to first item in the list.
void _append(DynDlist< T > &list) noexcept
T & _append(Dnode< T > *p) noexcept
void clear() noexcept
@brief Empties the container.
void erase(T &data) noexcept
T & get_last_ne() const noexcept
Return a modifiable reference to last item in the list.
void append(DynDlist &&list) noexcept
T & insert(const T &item)
Insert a copy of item at the beginning of the list.
T & _insert(Dnode< T > *p) noexcept
void append(const DynDlist &list)
Append all the elements of list after this.
~DynDlist()
Destructor.
T remove_first_ne() noexcept
Remove the first item of the list; return a copy of removed item.
T remove_last_ne() noexcept
Remove the last item of the list; return a copy of removed item.
DynDlist< T > & operator=(const DynDlist &list)
Assignment by copy.
T remove_first()
Remove the first item of the list; return a copy of removed item.
T & insert(T &&item)
Insert a moved item at the beginning of the list.
void split_list_ne(DynDlist &l, DynDlist &r) noexcept
Split the list in two.
DynDlist(const DynDlist &list)
Copy constructor; all items of list are copied.
T & top() const
constexpr bool is_empty() const noexcept
Definition htlist.H:419
Mixin providing equality comparison for sequence containers.
Definition ah-dry.H:1756
Common methods to the Aleph-w ( ) containers.
Definition ah-dry.H:642
Common sequential searching methods on containers.
Definition ah-dry.H:196
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:222
Mixin that adds STL begin()/end() and cbegin()/cend() to Aleph containers.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
Generic list of items stored in a container.
Definition ah-dry.H:1714
Generic traversal of the container through its iterator.
Definition ah-dry.H:67
Special constructors common to Aleph-w ( ) containers.
Definition ah-dry.H:586
gsl_rng * r
Doubly linked list node with typed data.
DynList< int > l