Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
htlist.H
1 # ifndef HTLIST_H
2 # define HTLIST_H
3 
4 # include <stdexcept>
5 # include <utility>
6 # include <initializer_list>
7 # include <ahFunction.H>
8 # include <ahFunctional.H>
9 # include <ahDry.H>
10 
11 # include <nana.h>
12 
13 # define NEXT(p) (p->get_next())
14 
15 namespace Aleph {
16 
17 class Slinknc
18 {
19  Slinknc * next;
20 
21 public:
22 
24  Slinknc() : next(NULL) { /* empty */ }
25 
27  Slinknc(const Slinknc &) : next(NULL) { /* empty */ }
28 
30  void reset()
31  {
32  I(this not_eq NULL);
33  next = NULL;
34  }
35 
37  bool is_empty() const
38  {
39  I(this != NULL);
40  return next == NULL;
41  }
42 
44  Slinknc & operator = (const Slinknc & link)
45  {
46  if (&link == this)
47  return *this;
48 
49  if (not is_empty())
50  throw std::invalid_argument("link is not empty");
51 
52  next = NULL;
53 
54  return *this;
55  }
56 
59  {
60  I(this not_eq NULL);
61  return next;
62  }
63 
71  void insert(Slinknc * p)
72  {
73  I(this not_eq NULL);
74  I(p not_eq NULL);
75  I(p->is_empty());
76  p->next = next;
77  next = p;
78  }
79 
89  {
90  I(this not_eq NULL);
91  Slinknc * ret_val = next;
92  next = ret_val->next;
93  ret_val->reset();
94  return ret_val;
95  }
96 
97  class Iterator
98  {
99  Slinknc * head;
100  Slinknc * curr;
101 
102  public:
103 
104  Iterator()
105  : head(NULL), curr(NULL)
106  {
107  // Empty
108  }
109 
111  : head(&list), curr(head)
112  {
113  // Empty
114  }
115 
116  Iterator(Slinknc * _head, Slinknc * _curr)
117  : head(_head), curr(_curr)
118  {
119  // Empty
120  }
121 
122  bool has_current() const
123  {
124  return curr != NULL;
125  }
126 
127  bool has_curr() const
128  {
129  return has_current();
130  }
131 
132  Slinknc * get_current() const
133  {
134  if (not has_current())
135  throw std::overflow_error("Iterator is at the end of the list");
136  return curr;
137  }
138 
139  Slinknc * get_curr() const
140  {
141  return get_current();
142  }
143 
144  void next()
145  {
146  if (not has_current())
147  throw std::overflow_error("Iterator is at the end of the list");
148  curr = curr->next;
149  }
150 
151  void reset_first()
152  {
153  curr = head;
154  }
155  };
156 };
157 
158 
159  template <typename T>
160 class Snodenc : public Slinknc
161 {
162  T data;
163 
164 public:
165 
167  T & get_data() { return data; }
168 
170  Snodenc() { /* empty*/ }
171 
173  Snodenc(const T & item) : data(item)
174  {
175  // empty
176  }
177 
178  Snodenc(T && item)
179  {
180  std::swap(data, item);
181  }
182 
191 
193  Snodenc *& get_next() { return (Snodenc*&) Slinknc::get_next(); }
194 
203 
205  Snodenc *& get_first() const { return Snodenc::get_next(); }
206 };
207 
208 
234 class HTList
235 {
236  Slinknc * head;
237  Slinknc * tail;
238 
239 public:
240 
242  HTList() : head(NULL), tail(NULL) { /* empty */ }
243 
245  HTList(Slinknc * l) : head(l), tail(l) { /* empty */ }
246 
248  bool is_empty() const { return head == NULL; }
249 
251  bool is_unitarian() const { return head != NULL and head == tail; }
252 
254  bool is_unitarian_or_empty() const { return head == tail; }
255 
257  Slinknc * get_head() { return head; }
258 
260  Slinknc * get_tail() { return tail; }
261 
263  Slinknc * get_first() { return get_head(); }
264 
266  Slinknc * get_last() { return get_tail(); }
267 
271  {
272  std::swap(head, l.head);
273  std::swap(tail, l.tail);
274  return *this;
275  }
276 
278  void insert(Slinknc * link)
279  {
280  I(NEXT(link) == NULL);
281 
282  if (head == NULL)
283  {
284  I(tail == NULL);
285  head = tail = link;
286  return;
287  }
288 
289  NEXT(link) = head;
290  head = link;
291  }
292 
294  void push(Slinknc * link) { insert(link); }
295 
297  void append(Slinknc * link)
298  {
299  I(link != NULL and NEXT(link) == NULL);
300 
301  if (head == NULL)
302  {
303  I(tail == NULL);
304  head = tail = link;
305  return;
306  }
307 
308  NEXT(tail) = link;
309  tail = link;
310  }
311 
314  void append(HTList & l)
315  {
316  if (l.is_empty())
317  return;
318 
319  if (this->is_empty())
320  {
321  this->swap(l);
322  return;
323  }
324 
325  NEXT(tail) = l.head;
326  tail = l.tail;
327  l.head = l.tail = NULL;
328  }
329 
331  void put(Slinknc * link) { append(link); }
332 
334  void concat(HTList & l) { append(l); }
335 
337  void concat_list(HTList & l) { append(l); }
338 
340  void insert(HTList & l)
341  {
342  l.append(*this);
343  this->swap(l);
344  }
345 
348  void insert(Slinknc * link, HTList & list)
349  {
350  NEXT(link) = list.head;
351  tail = list.tail;
352  list.head = list.tail = NULL;
353  }
354 
358  {
359  if (is_empty())
360  throw std::underflow_error("HTList is empty");
361 
362  Slinknc * ret_val = head;
363  if (head == tail)
364  head = tail = NULL;
365  else
366  {
367  head = NEXT(head);
368  if (head == NULL)
369  tail = NULL;
370  }
371 
372  ret_val->reset();
373 
374  return ret_val;
375  }
376 
378  Slinknc * remove_first() { return remove_head(); }
379 
382  bool remove(Slinknc * link)
383  {
384  if (is_empty())
385  throw std::domain_error("Removing from a empty list");
386 
387  if (link == head)
388  {
389  head = NEXT(head);
390  link->reset();
391  return true;
392  }
393 
394  for (Slinknc * prev = head, * p = NEXT(head); p != NULL;
395  prev = p, p = NEXT(p))
396  if (p == link)
397  {
398  NEXT(prev) = NEXT(p);
399  if (link == tail)
400  tail = prev;
401  link->reset();
402  return true;
403  }
404 
405  return false;
406  }
407 
409  Slinknc * pop() { return remove_head(); }
410 
415  size_t split_list(HTList & l, HTList & r)
416  {
417  I(l.is_empty() and r.is_empty()); // l y r deben estar vacías
418 
419  if (is_empty())
420  return 0;
421 
422  if (is_unitarian())
423  {
424  swap(l);
425  return 1;
426  }
427 
428  size_t count = 0;
429  Slinknc * p = head;
430  Slinknc * q = head;
431  while (true)
432  {
433  q = NEXT(q); ++count;
434 
435  if (q == tail or q == NULL)
436  break;
437 
438  p = NEXT(p);
439  q = NEXT(q); ++count;
440  if (q == tail or q == NULL)
441  break;
442  }
443 
444  l.head = head;
445  l.tail = p;
446 
447  r.head = NEXT(p);
448  r.tail = tail;
449 
450  head = tail = NULL;
451 
452  return count;
453  }
454 
456  size_t split(HTList & l, HTList & r)
457  {
458  return split_list(l, r);
459  }
460 
462  size_t reverse()
463  {
464  HTList tmp;
465 
466  size_t count = 0;
467  while (not is_empty())
468  {
469  tmp.insert(remove_first());
470  ++count;
471  }
472 
473  swap(tmp);
474 
475  return count;
476  }
477 
479  size_t reverse_list()
480  {
481  return reverse();
482  }
483 
486  void cut(Slinknc * link, HTList & list)
487  {
488  I(list.is_empty());
489 
490  list.head = NEXT(link);
491  list.tail = tail;
492 
493  tail = link;
494  NEXT(link) = NULL;
495  }
496 
498  void cut_list(Slinknc * link, HTList & list) { cut(link, list); }
499 
503  {
504  while (not is_empty())
505  delete remove_head();
506  }
507 
511  class Iterator
512  {
513  HTList * lptr;
514  Slinknc * curr;
515  Slinknc * prev;
516 
517  public:
518 
519  Iterator(const Iterator & it)
520  : lptr(it.lptr), curr(it.curr), prev(it.prev) { /* empty */ }
521 
522  Iterator() : lptr(NULL), curr(NULL), prev(NULL) { /* empty */ }
523 
524  Iterator(const HTList & list)
525  : lptr(& (HTList&) list), curr(lptr->head), prev(curr)
526  { /* empty */ }
527 
528  void reset()
529  {
530  prev = curr = lptr->head;
531  }
532 
533  void reset_first() { reset(); }
534 
535  Iterator & operator = (const Iterator & it)
536  {
537  lptr = it.lptr;
538  curr = it.curr;
539  prev = it.prev;
540  return *this;
541  }
542 
543  bool has_curr() const { return curr != NULL; }
544 
545  bool has_current() const { return has_curr(); }
546 
547  Slinknc * get_curr() const
548  {
549  if (curr == NULL)
550  throw std::overflow_error("Iterator overflow");
551 
552  return curr;
553  }
554 
555  Slinknc * get_current() const { return get_curr(); }
556 
557  void next()
558  {
559  if (curr == lptr->head)
560  {
561  I(prev == lptr->head);
562  curr = NEXT(curr);
563  }
564  else if (curr == lptr->tail)
565  {
566  I(NEXT(prev) == curr);
567  curr = NULL;
568  }
569  else
570  {
571  I(NEXT(prev) == curr);
572  prev = curr;
573  curr = NEXT(curr);
574  I(NEXT(prev) == curr);
575  }
576  }
577 
578  Slinknc * del()
579  {
580  if (not has_curr())
581  throw std::overflow_error("Iterator overflow");
582 
583  Slinknc * ret_val = NULL;
584  if (curr == lptr->head) // first item removal
585  {
586  ret_val = lptr->remove_first();
587  prev = curr = lptr->head;
588  }
589  else if (curr == lptr->tail) // last item removal
590  {
591  I(NEXT(prev) == curr);
592  ret_val = curr;
593  NEXT(prev) = NEXT(curr);
594  lptr->tail = prev;
595  curr = NULL; // put in overflow
596  }
597  else
598  {
599  I(NEXT(prev) == curr);
600  ret_val = curr;
601  NEXT(prev) = NEXT(curr);
602  curr = NEXT(curr);
603  }
604 
605  ret_val->reset();
606  return ret_val;
607  }
608  };
609 
610  void insert(const Iterator & it, HTList & list)
611  {
612  insert(it.get_curr(), list);
613  }
614 
617  void cut_list(const Iterator & it, HTList & list)
618  {
619  cut(it.get_curr(), list);
620  }
621 
622  size_t size() const
623  {
624  size_t count = 0;
625 
626  for (Iterator it(*this); it.has_curr(); it.next())
627  ++count;
628 
629  return count;
630  }
631 };
632 
633 
644  template <typename T = int>
645 class DynList : public HTList
646 {
647 public:
648 
649  DynList & swap(DynList & l) { return (DynList&) HTList::swap(l); }
650 
651  DynList() { /* empty */ }
652 
653  typedef T Item_Type;
654 
655  typedef T Key_Type;
656 
657 private:
658 
659  T & __insert(Snodenc<T> * p)
660  {
661  HTList::insert(p);
662  return p->get_data();
663  }
664 
665  T & __append(Snodenc<T> * p)
666  {
667  HTList::append(p);
668  return p->get_data();
669  }
670 
671 public:
672 
674  T & insert(const T & item)
675  {
676  return __insert(new Snodenc<T> (item));
677  }
678 
679  T & insert(T && item)
680  {
681  return __insert(new Snodenc<T> (std::move(item)));
682  }
683 
685  T & append(const T & item)
686  {
687  return __append(new Snodenc<T> (item));
688  }
689 
690  T & append(T && item)
691  {
692  return __append(new Snodenc<T> (std::move(item)));
693  }
694 
696  DynList(const T & item)
697  {
698  insert(item);
699  }
700 
702  DynList(T && item)
703  {
704  insert(std::move(item));
705  }
706 
708  T remove()
709  {
710  Slinknc * l = this->HTList::remove_head();
711  Snodenc<T> * p = static_cast<Snodenc<T>*> (l);
712  T ret_val = std::move(p->get_data());
713  delete p;
714 
715  return ret_val;
716  }
717 
719  T remove_first() { return remove(); }
720 
721  T & get()
722  {
723  if (is_empty())
724  throw std::underflow_error("List is empty");
725 
726  Snodenc<T> * p = static_cast<Snodenc<T>*> (this->HTList::get_first());
727  return p->get_data();
728  }
729 
730  T & get_last()
731  {
732  if (is_empty())
733  throw std::underflow_error("List is empty");
734 
735  Snodenc<T> * p = static_cast<Snodenc<T>*> (this->HTList::get_last());
736  return p->get_data();
737  }
738 
739  const T & get_last() const
740  {
741  return const_cast<DynList*>(this)->get_last();
742  }
743 
744  T & get_first() { return get(); }
745 
746  const T & get_first() const { return get(); }
747 
748  T & get() const
749  {
750  DynList * ptr = const_cast<DynList*>(this);
751  return ptr->get();
752  }
753 
755  void empty()
756  {
757  while (not is_empty())
758  remove();
759 
760  I(this->is_empty());
761  }
762 
763  ~DynList() { empty(); }
764 
769  class Iterator : public HTList::Iterator
770  {
771  public:
772 
773  typedef T Item_Type;
774 
775  typedef Iterator Iterator_Type;
776 
777  Iterator() { /* empty */ }
778 
779  Iterator(const DynList & list) : HTList::Iterator(list) { /* empty */ }
780 
781  T & get_curr() const
782  {
783  return ((Snodenc<T>*) (HTList::Iterator::get_curr()))->get_data();
784  }
785 
786  T & get_current() const
787  {
788  return get_curr();
789  }
790 
791  T del()
792  {
793  Snodenc<T> * p = (Snodenc<T> *) this->HTList::Iterator::del();
794  T ret_val = std::move(p->get_data());
795  delete p;
796  return ret_val;
797  }
798  };
799 
803  template <class Equal = Aleph::equal_to<T>>
804  bool remove(const T & item)
805  {
806  for (Iterator it(*this); it.has_curr(); it.next())
807  if (Equal () (it.get_curr(), item))
808  {
809  it.del();
810  return true;
811  }
812 
813  return false;
814  }
815 
817  DynList(const DynList & l)
818  {
819  for (typename DynList::Iterator it(l); it.has_curr(); it.next())
820  append(it.get_curr());
821  }
822 
825  {
826  swap(l);
827  }
828 
829  DynList(std::initializer_list<T> l)
830  {
831  std::for_each(l.begin(), l.end(), /* Lambda */ [this] (const T & item)
832  {
833  append(item);
834  });
835  }
836 
839  {
840  if (&l == this)
841  return *this;
842 
843  empty();
844 
845  for (typename DynList::Iterator it(l); it.has_curr(); it.next())
846  append(it.get_curr());
847 
848  return *this;
849  }
850 
851  DynList & operator = (DynList && l)
852  {
853  return (DynList&) this->swap(l);
854  }
855 
857  void append(DynList && list)
858  {
859  HTList::append(list);
860  }
861 
863  void insert(DynList && list)
864  {
865  HTList::insert(list);
866  }
867 
870  void append(const DynList & list)
871  {
872  if (&list == this)
873  return;
874 
875  DynList copy = list;
876  HTList::append(copy);
877  }
878 
881  void insert(const DynList & list)
882  {
883  if (&list == this)
884  return;
885 
886  DynList tmp = list;
887  HTList::insert(tmp);
888  }
889 
890  T & get(const size_t & i)
891  {
892  Iterator it(*this);
893 
894  for (size_t __i = 0 ; it.has_current() and __i < i; it.next(), ++__i);
895 
896  return it.get_current();
897  }
898 
899  T & operator [] (const size_t & i)
900  {
901  return get(i);
902  }
903 
904  Generic_Traverse(T);
905 
906  Functional_Methods(T);
907 };
908 
909 
910 # undef NEXT
911 
912 } // end namespace Aleph
913 
914 
915 # endif // HTLIST_H
void insert(HTList &l)
Inserta toda la lista l antes de this; l deviene vacía.
Definition: htlist.H:340
Slinknc(const Slinknc &)
Constructor copia; coloca enlace a que apunte a NULL.
Definition: htlist.H:27
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Definition: ahAlgo.H:127
void reset()
Reinicia enlace a que apunte a NULL.
Definition: htlist.H:30
Definition: htlist.H:160
T remove_first()
Definition: htlist.H:719
Snodenc *& get_next()
Retorna el nodo siguiente a this.
Definition: htlist.H:193
Slinknc *& get_next()
Retorna el siguiente enlace.
Definition: htlist.H:58
void empty()
Elimina todos los elementos de la lista.
Definition: htlist.H:755
size_t reverse()
Invierte los elementos de la lista. Retorna el tamaño de la lista.
Definition: htlist.H:462
void cut_list(Slinknc *link, HTList &list)
Definition: htlist.H:498
void insert(Slinknc *link, HTList &list)
Definition: htlist.H:348
void put(Slinknc *link)
Inserta link al final de la lista.
Definition: htlist.H:331
void insert(DynList &&list)
Copia en tiempo constante los elementos de list al inicio de this.
Definition: htlist.H:863
size_t split(HTList &l, HTList &r)
Definition: htlist.H:456
void append(Slinknc *link)
Inserta link como último elemento.
Definition: htlist.H:297
void insert(Slinknc *link)
Inserta link como primer elemento.
Definition: htlist.H:278
Snodenc * remove_first()
Definition: htlist.H:202
Slinknc * pop()
Elimina el primer elemento de this.
Definition: htlist.H:409
DynList(T &&item)
Crea una lista con elemento item.
Definition: htlist.H:702
DynList(DynList &&l)
Crea una lista copia de l.
Definition: htlist.H:824
T & get_data()
Retorna una referencia al dato contenido en el nodo.
Definition: htlist.H:167
Slinknc * get_last()
Retorna el último elemento de la lista.
Definition: htlist.H:266
bool is_empty() const
Retorna true si la lista está vacía.
Definition: htlist.H:248
HTList & swap(HTList &l)
Definition: htlist.H:270
bool is_unitarian_or_empty() const
Retorna true si la lista tiene un elemento o está vacía.
Definition: htlist.H:254
void concat_list(HTList &l)
Definition: htlist.H:337
Slinknc * get_head()
Retorna la cabeza de la lista (el primer elemento)
Definition: htlist.H:257
T & insert(const T &item)
Inserta un item como primer elemento.
Definition: htlist.H:674
Snodenc()
Constructor vacío.
Definition: htlist.H:170
Snodenc(const T &item)
Constructor que copia dato.
Definition: htlist.H:173
Snodenc * remove_next()
Definition: htlist.H:190
Definition: htlist.H:234
Slinknc * get_tail()
Retorna la cola de la lista (el último elemento)
Definition: htlist.H:260
Slinknc & operator=(const Slinknc &link)
Asignación; coloca enlace a que apunte a NULL.
Definition: htlist.H:44
Operation for_each(Itor beg, const Itor &end, Operation op)
Definition: ahAlgo.H:83
Slinknc * get_first()
Retorna el primer elemento de la lista.
Definition: htlist.H:263
Slinknc()
Constructor vacío.
Definition: htlist.H:24
Definition: htlist.H:17
Recorre condicionalmente el contenedor y ejecuta una operation mientras ésta retorne true...
void remove_all_and_delete()
Definition: htlist.H:502
void insert(Slinknc *p)
Definition: htlist.H:71
bool is_empty() const
Retorna true si this está vacío (apunta a NULL)
Definition: htlist.H:37
void cut(Slinknc *link, HTList &list)
Definition: htlist.H:486
Snodenc *& get_first() const
Retorna el nodo siguiente a this.
Definition: htlist.H:205
void insert(const DynList &list)
Definition: htlist.H:881
DynList(const DynList &l)
Crea una lista copia de l.
Definition: htlist.H:817
size_t split_list(HTList &l, HTList &r)
Definition: htlist.H:415
bool is_unitarian() const
Retorna true si la lista contiene exactamente un solo elemento.
Definition: htlist.H:251
DynList & operator=(const DynList &l)
Copia a this los elementos de l.
Definition: htlist.H:838
Slinknc * remove_first()
Elimina el primer elemento de this.
Definition: htlist.H:378
void cut_list(const Iterator &it, HTList &list)
Definition: htlist.H:617
Slinknc * remove_head()
Definition: htlist.H:357
Slinknc * remove_next()
Definition: htlist.H:88
HTList(Slinknc *l)
Inicializa una lista de un solo Slinknc.
Definition: htlist.H:245
Definition: htlist.H:769
void concat(HTList &l)
Concatena a this toda la lista l; l deviene vacía.
Definition: htlist.H:334
Definition: ahDry.H:13
Definition: htlist.H:511
void append(DynList &&list)
Copia en tiempo constante los elementos de list al final de this.
Definition: htlist.H:857
T & append(const T &item)
Inserta un item como último elemento.
Definition: htlist.H:685
size_t reverse_list()
Definition: htlist.H:479
void append(const DynList &list)
Definition: htlist.H:870
void append(HTList &l)
Definition: htlist.H:314
Definition: List.H:23
HTList()
Inicializa una lista vacía.
Definition: htlist.H:242
DynList(const T &item)
Crea una lista con elemento item.
Definition: htlist.H:696
void push(Slinknc *link)
Inserta link como primer elemento.
Definition: htlist.H:294
Definition: htlist.H:97

Leandro Rabindranath León