Aleph-w  1.9
General library for algorithms and data structures
tpl_dynDlist.H
1 
2 /* Aleph-w
3 
4  / \ | | ___ _ __ | |__ __ __
5  / _ \ | |/ _ \ '_ \| '_ \ ____\ \ /\ / / Data structures & Algorithms
6  / ___ \| | __/ |_) | | | |_____\ V V / version 1.9b
7  /_/ \_\_|\___| .__/|_| |_| \_/\_/ https://github.com/lrleon/Aleph-w
8  |_|
9 
10  This file is part of Aleph-w library
11 
12  Copyright (c) 2002-2018 Leandro Rabindranath Leon & Alejandro Mujica
13 
14  This program is free software: you can redistribute it and/or modify
15  it under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  This program is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27 # ifndef TPL_DYNDLIST_H
28 # define TPL_DYNDLIST_H
29 
30 # include <ahFunctional.H>
31 # include <ahDry.H>
32 # include <ah-args-ctor.H>
33 # include <ahIterator.H>
34 # include <ah-iterator.H>
35 # include <tpl_dnode.H>
36 
37 using namespace Aleph;
38 
39 namespace Aleph {
40 
41 # include <ah-dry.H>
42 
50  template <typename T = int>
51 class DynDlist
52  : public Dnode<T>,
53  public GenericTraverse<DynDlist<T>>,
54  public SpecialCtors<DynDlist<T>, T>,
55  public LocateFunctions<DynDlist<T>, T>,
56  public FunctionalMethods<DynDlist<T>, T>,
57  public GenericItems<DynDlist<T>, T>,
58  public StlAlephIterator<DynDlist<T>>
59 {
60  size_t num_elem = 0;
61 
62 public:
63 
65  using Set_Type = DynDlist;
66 
68  using Item_Type = T;
69 
71  using Key_Type = T;
72 
74  const size_t & size() const noexcept { return num_elem; }
75 
76  DynDlist() { /* Empty */ }
77 
78  // using CtorBase = SpecialCtors<DynDlist<T>, T>;
79  // using CtorBase::CtorBase;
80 
81  // /** Construct a new list with copies of elements of list `l`
82 
83  // \param[in] l list to be copied
84  // \throw bad_alloc if there is no enough memory
85  // */
86  // DynDlist(const DynList<T> & l) : Dnode<T>(), CtorBase(l) {}
87 
89 
90  void empty() noexcept
91  {
92  while (not this->is_empty())
93  delete this->Dnode<T>::remove_next();
94 
95  num_elem = 0;
96  }
97 
99  {
100  empty();
101  }
102 
103 private:
104 
105  T & __insert(Dnode<T> * p) noexcept
106  {
107  Dnode<T>::insert(p);
108  ++num_elem;
109  return p->get_data();
110  }
111 
112  T & __append(Dnode<T> * p) noexcept
113  {
114  Dnode<T>::append(p);
115  ++num_elem;
116  return p->get_data();
117  }
118 
119 public:
120 
127  T & insert(const T & item)
128  {
129  return __insert(new Dnode<T> (item));
130  }
131 
138  T & insert(T && item)
139  {
140  return __insert(new Dnode<T> (std::forward<T>(item)));
141  }
142 
149  T & append(const T & item)
150  {
151  return __append(new Dnode<T> (item));
152  }
153 
160  T & append(T && item)
161  {
162  return __append(new Dnode<T> (std::forward<T>(item)));
163  }
164 
165  private:
166 
167  void __insert(DynDlist<T> & list) noexcept
168  {
169  Dlink::insert_list(&list);
170  num_elem += list.num_elem;
171  list.num_elem = 0;
172 
173  assert(list.is_empty());
174  }
175 
176  void __append(DynDlist<T> & list) noexcept
177  {
178  Dlink::append_list(&list);
179  num_elem += list.num_elem;
180  list.num_elem = 0;
181 
182  assert(list.is_empty());
183  }
184 
185  public:
186 
191  void insert(const DynDlist & list)
192  {
193  auto l = list; // perform a copy of list
194  __insert(l);
195  }
196 
198  void insert(DynDlist && list) noexcept
199  {
200  __insert(list);
201  }
202 
207  void append(const DynDlist & list) noexcept
208  {
209  auto l = list; // perform a copy of list
210  __append(l);
211  }
212 
214  void append(DynDlist && list) noexcept
215  {
216  __append(list);
217  }
218 
220  T & get_first_ne() const noexcept
221  {
222  return this->get_next()->get_data();
223  }
224 
226  T & get_last_ne() const noexcept
227  {
228  return this->get_prev()->get_data();
229  }
230 
232  T & get_first() const
233  {
234  if (this->is_empty())
235  throw std::underflow_error("DynDlist is empty");
236  return get_first_ne();
237  }
238 
240  T & get_last() const
241  {
242  if (this->is_empty())
243  throw std::underflow_error("DynDlist is empty");
244  return get_last_ne();
245  }
246 
251  T remove_first_ne() noexcept
252  {
253  Dnode<T> * ptr = this->remove_next();
254  T retVal = ptr->get_data();
255  delete ptr;
256  --num_elem;
257 
258  return retVal;
259  }
260 
265  T remove_last_ne() noexcept
266  {
267  Dnode<T> * ptr = this->remove_prev();
268  T retVal = ptr->get_data();
269  delete ptr;
270  --num_elem;
271 
272  return retVal;
273  }
274 
281  {
282  if (this->is_empty())
283  throw std::underflow_error("DynDlist is empty");
284  return remove_first_ne();
285  }
286 
293  {
294  if (this->is_empty())
295  throw std::underflow_error("DynDlist is empty");
296  return remove_last_ne();
297  }
298 
300  T & put(const T & item) { return append(item); }
301 
303  T & put(T && item) { return append(std::forward<T>(item)); }
304 
306  T get() { return remove_first(); }
307 
310  T & rear() { return get_last(); }
311 
314  T & front() { return get_first(); }
315 
317  T & push(const T & item) { return insert(item); }
318 
320  T & push(T && item) { return insert(std::forward<T>(item)); }
321 
323  T pop() { return remove_first(); }
324 
326  T & top() const { return get_first(); }
327 
341  void remove(T & data) noexcept
342  {
343  Dnode<T> * p = Dnode<T>::data_to_node(data);
344  p->del();
345  delete p;
346  --num_elem;
347  }
348 
350  void erase(T & data) noexcept
351  {
352  remove(data);
353  }
354 
357  void swap(DynDlist & l) noexcept
358  {
359  std::swap(num_elem, l.num_elem);
360  this->Dlink::swap(&l);
361  }
362 
374  void split_list_ne(DynDlist & l, DynDlist & r) noexcept
375  {
376  Dlink::split_list(l, r);
377  l.num_elem = r.num_elem = num_elem/2;
378 
379  if (num_elem % 2 == 1) // ¿es num_elem impar?
380  l.num_elem++;
381 
382  num_elem = 0;
383  }
384 
396  void split_list(DynDlist & l, DynDlist & r)
397  {
398  if ((not l.is_empty()) or (not r.is_empty()))
399  throw std::domain_error("lists are not empty");
400  split_list_ne(l, r);
401  }
402 
404  void split(DynDlist & l, DynDlist & r)
405  {
406  split_list(l, r);
407  }
408 
413  class Iterator : public Dnode<T>::Iterator
414  {
415  DynDlist * list_ptr; // puntero a la lista
416  long pos; // posición del elemento actual en la secuencia
417 
418  using Base = typename Dnode<T>::Iterator;
419 
420  public:
421 
424 
426  using Item_Type = T;
427 
429  long get_pos() const noexcept { return pos; }
430 
433  void next_ne() noexcept
434  {
436  pos++;
437  }
438 
441  void next()
442  {
444  pos++;
445  }
446 
449  void prev()
450  {
452  pos--;
453  }
454 
456  void reset_first() noexcept
457  {
459  pos = 0;
460  }
461 
463  void reset_last() noexcept
464  {
466  pos = list_ptr->num_elem - 1;
467  }
468 
470  void end() noexcept
471  {
472  put_itor_at_the_end(*this);
473  }
474 
476  Iterator(const DynDlist<T> & list) noexcept
477  : Base(list), list_ptr(&const_cast<DynDlist&>(list)), pos(0)
478  {
479  // empty
480  }
481 
482  Iterator() noexcept : list_ptr(nullptr) { /* empty */ }
483 
484  Iterator & operator = (const Iterator & it) noexcept
485  {
487  list_ptr = it.list_ptr;
488  pos = it.pos;
489 
490  return *this;
491  }
492 
495  T & get_curr() const
496  {
497  return Dnode<T>::Iterator::get_curr()->get_data();
498  }
499 
500  T & get_curr_ne() const noexcept
501  {
502  return Dnode<T>::Iterator::get_curr_ne()->get_data();
503  }
504 
514  void insert(const T & item)
515  {
516  if (not this->has_curr())
517  throw std::overflow_error ("DynDlist Iterator has not current");
518 
519  Dnode<T>::Iterator::get_curr()->insert(new Dnode<T>(item));
520  ++list_ptr->num_elem;
521  }
522 
533  void insert(T && item)
534  {
535  if (not this->has_curr())
536  throw std::overflow_error ("DynDlist Iterator has not current");
537 
539  insert(new Dnode<T>(std::forward<T>(item)));
540  ++list_ptr->num_elem;
541  }
542 
552  void append(const T & item)
553  {
554  if (not this->has_curr())
555  throw std::overflow_error ("DynDlist Iterator has not current");
556 
557  Dnode<T>::Iterator::get_curr()->append(new Dnode<T>(item));
558  ++list_ptr->num_elem;
559  }
560 
571  void append(T && item)
572  {
573  if (not this->has_curr())
574  throw std::overflow_error ("DynDlist Iterator has not current");
575 
577  append(new Dnode<T>(std::forward<T>(item)));
578  ++list_ptr->num_elem;
579  }
580 
596  void insert_list(DynDlist & list)
597  {
598  if (not this->has_curr())
599  throw std::overflow_error ("DynDlist Iterator has not current");
600 
601  Dnode<T>::Iterator::get_curr()->insert_list(&list);
602  list_ptr->num_elem += list.num_elem;
603  list.num_elem = 0;
604 
605  assert(list.is_empty());
606  }
607 
623  void append_list(DynDlist & list)
624  {
625  if (not this->has_curr())
626  throw std::overflow_error ("DynDlist Iterator has not current");
627 
628  Dnode<T>::Iterator::get_curr()->append_list(&list);
629  list_ptr->num_elem += list.num_elem;
630  list.num_elem = 0;
631 
632  assert(list.is_empty());
633  }
634 
641  T del()
642  {
643  if (not this->has_curr())
644  throw std::overflow_error ("DynDlist Iterator has not current");
645 
647  T ret_val = ptr->get_data();
649  ptr->del();
650  delete ptr;
651  --list_ptr->num_elem;
652  return ret_val;
653  }
654  };
655 
665  DynDlist<T> & operator = (const DynDlist & list)
666  {
667  if (this == &list)
668  return *this;
669 
670  empty();
671 
672  for (typename DynDlist<T>::Iterator itor(const_cast<DynDlist&>(list));
673  itor.has_curr(); itor.next_ne())
674  this->append(itor.get_curr_ne());
675 
676  return *this;
677  }
678 
686  DynDlist(const DynDlist & list) : DynDlist()
687  {
688  assert(this->is_empty());
689 
690  for (typename DynDlist<T>::Iterator itor(const_cast<DynDlist&>(list));
691  itor.has_curr();itor.next_ne())
692  this->append(itor.get_curr_ne());
693  }
694 
703  DynDlist(DynDlist<T> && list) noexcept
704  : DynDlist()
705  {
706  swap(list);
707  }
708 
717  DynDlist<T> & operator = (DynDlist && list) noexcept
718  {
719  swap(list);
720  return *this;
721  }
722 
725  T & operator [] (const size_t & n) const
726  {
727  typename DynDlist<T>::Iterator it(*this);
728 
729  for (int i = 0; i < n and it.has_curr(); i++, it.next_ne()) ;
730 
731  return it.get_curr();
732  }
733 
734  DynDlist & reverse() noexcept
735  {
736  Dlink::reverse();
737  return *this;
738  }
739 
740  DynDlist & rev() noexcept { return reverse(); }
741 
747  {
748  DynDlist<T> ret;
749  for (auto it = this->get_it(); it.has_curr(); it.next_ne())
750  ret.insert(it.get_curr_ne());
751  return ret;
752  }
753 
754  DynDlist<T> rev() const { return reverse(); }
755 };
756 
757 } // end namespace Aleph
758 
759 # endif /* TPL_DYNDLIST_H */
760 
Special_Ctors(DynDlist, T)
static Dnode * data_to_node(T &data) noexcept
Definition: tpl_dnode.H:194
T & append(T &&item)
Definition: tpl_dynDlist.H:160
Definition: htlist.H:450
Definition: htlist.H:1290
T & rear()
Definition: tpl_dynDlist.H:310
void erase(T &data) noexcept
Definition: tpl_dynDlist.H:350
void append(DynDlist &&list) noexcept
Definition: tpl_dynDlist.H:214
void split_list_ne(DynDlist &l, DynDlist &r) noexcept
Definition: tpl_dynDlist.H:374
void swap(DynDlist &l) noexcept
Definition: tpl_dynDlist.H:357
Definition: htlist.H:133
T remove_last_ne() noexcept
Definition: tpl_dynDlist.H:265
Iterator(const DynDlist< T > &list) noexcept
Initialize the iterator to the first item of list
Definition: tpl_dynDlist.H:476
T & top() const
Definition: tpl_dynDlist.H:326
T & put(T &&item)
Definition: tpl_dynDlist.H:303
void append(const DynDlist &list) noexcept
Definition: tpl_dynDlist.H:207
auto get_it() const
Definition: htlist.H:151
Definition: tpl_dynDlist.H:51
long get_pos() const noexcept
Return the ordinal position of current item.
Definition: tpl_dynDlist.H:429
void append(T &&item)
Definition: tpl_dynDlist.H:571
~DynDlist()
Destructor.
Definition: tpl_dynDlist.H:98
T & front()
Definition: tpl_dynDlist.H:314
void insert(const DynDlist &list)
Definition: tpl_dynDlist.H:191
void reset_last() noexcept
Reset the iterator to the last item.
Definition: tpl_dynDlist.H:463
void append_list(DynDlist &list)
Definition: tpl_dynDlist.H:623
T & get_last() const
Return a modifiable reference to last item in the list.
Definition: tpl_dynDlist.H:240
T & insert(T &&item)
Definition: tpl_dynDlist.H:138
T & put(const T &item)
Definition: tpl_dynDlist.H:300
T & push(const T &item)
Definition: tpl_dynDlist.H:317
T pop()
Definition: tpl_dynDlist.H:323
typename GT::Node * Key_Type
The type of element that stores the container.
Definition: tpl_dynDlist.H:71
Definition: htlist.H:45
DynDlist(DynDlist< T > &&list) noexcept
Definition: tpl_dynDlist.H:703
Dnode< T > * get_curr_ne() const noexcept
Return the current link guaranteeing no exception. Be careful.
Definition: tpl_dnode.H:221
Dnode< T > *& get_next() const noexcept
Return the next node to this
Definition: tpl_dnode.H:53
Definition: tpl_dynDlist.H:413
T & push(T &&item)
Definition: tpl_dynDlist.H:320
T remove_last()
Definition: tpl_dynDlist.H:292
void prev()
Definition: tpl_dynDlist.H:449
void insert(DynDlist &&list) noexcept
Definition: tpl_dynDlist.H:198
T & get_first_ne() const noexcept
Return a modifiable reference to first item in the list.
Definition: tpl_dynDlist.H:220
Definition: ah-comb.H:35
void insert(const T &item)
Definition: tpl_dynDlist.H:514
void insert(T &&item)
Definition: tpl_dynDlist.H:533
void end() noexcept
Put theiterator at the end state (where there is no current item)
Definition: tpl_dynDlist.H:470
T & get_data() noexcept
Return a modifiable reference to the data contained in the node.
Definition: tpl_dnode.H:178
T & get_first() const
Return a modifiable reference to first item in the list.
Definition: tpl_dynDlist.H:232
Dnode< T > * remove_prev() noexcept
Remove the previous node to this; return its address.
Definition: tpl_dnode.H:59
DynDlist< T > reverse() const
Definition: tpl_dynDlist.H:746
void next_ne() noexcept
Definition: tpl_dynDlist.H:433
Dnode< T > *& get_prev() const noexcept
Return the previous node to this
Definition: tpl_dnode.H:56
void reset_first() noexcept
Reset the iterator to the first item.
Definition: tpl_dynDlist.H:456
T & operator[](const size_t &n) const
Definition: tpl_dynDlist.H:725
DynDlist(const DynDlist &list)
Definition: tpl_dynDlist.H:686
void next()
Definition: tpl_dynDlist.H:441
Dnode< T > * remove_next() noexcept
Remove the next node to this; return its address.
Definition: tpl_dnode.H:62
Dnode< T > * get_curr() const
Definition: tpl_dnode.H:231
void split_list(DynDlist &l, DynDlist &r)
Definition: tpl_dynDlist.H:396
Definition: tpl_dnode.H:206
void empty() noexcept
Empty the list.
Definition: tpl_dynDlist.H:90
const size_t & size() const noexcept
Return the number of elements (constant time)
Definition: tpl_dynDlist.H:74
T & get_curr() const
Definition: tpl_dynDlist.H:495
T remove_first_ne() noexcept
Definition: tpl_dynDlist.H:251
T & get_last_ne() const noexcept
Return a modifiable reference to last item in the list.
Definition: tpl_dynDlist.H:226
void insert_list(DynDlist &list)
Definition: tpl_dynDlist.H:596
T del()
Definition: tpl_dynDlist.H:641
Definition: htlist.H:406
typename GT::Node * Item_Type
The type of element that stores the container.
Definition: tpl_dynDlist.H:68
Definition: List.H:49
T remove_first()
Definition: tpl_dynDlist.H:280
void append(const T &item)
Definition: tpl_dynDlist.H:552
void split(DynDlist &l, DynDlist &r)
Definition: tpl_dynDlist.H:404
T & insert(const T &item)
Definition: tpl_dynDlist.H:127
T & append(const T &item)
Definition: tpl_dynDlist.H:149
Definition: dlink.H:37

Leandro Rabindranath León