Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
dlink.H
1 
2 # ifndef DLINK_H
3 # define DLINK_H
4 
5 # include <aleph.H>
6 
7 using namespace Aleph;
8 
9 namespace Aleph {
10 
24 class Dlink
25 {
26 protected:
27 
28  mutable Dlink * prev;
29  mutable Dlink * next;
30 
31 public:
32 
33  Dlink & swap(Dlink & l)
34  {
35  std::swap(prev, l.prev);
36  std::swap(next, l.next);
37 
38  return *this;
39  }
40 
41  Dlink() : prev(this), next(this) { /* empty */ }
42 
44  Dlink(const Dlink &) { reset(); }
45 
46  Dlink(Dlink && l) : prev(this), next(this)
47  {
48  swap(l);
49  }
50 
59  Dlink & operator = (const Dlink & l)
60  {
61  if (this == &l)
62  return *this;
63 
64  if (not is_empty())
65  throw std::invalid_argument ("left list must be empty");
66 
67  reset();
68 
69  return *this;
70  }
71 
72  Dlink & operator = (Dlink && l)
73  {
74  return swap(l);
75  }
76 
77  void reset()
78  {
79  I(this != NULL);
80  next = prev = this;
81  }
82 
83  void init()
84  {
85  reset();
86  }
87 
93  void swap(Dlink * link)
94  {
95  if (is_empty() and link->is_empty())
96  return;
97 
98  if (is_empty())
99  {
100  link->next->prev = this;
101  link->prev->next = this;
102  next = link->next;
103  prev = link->prev;
104  link->reset();
105 
106  return;
107  }
108 
109  if (link->is_empty())
110  {
111  next->prev = link;
112  prev->next = link;
113  link->next = next;
114  link->prev = prev;
115  reset();
116 
117  return;
118  }
119 
120  std::swap(prev->next, link->prev->next);
121  std::swap(next->prev, link->next->prev);
122  std::swap(prev, link->prev);
123  std::swap(next, link->next);
124  }
125 
127  bool is_empty() const { return this == next and this == prev; }
128 
130  bool is_unitarian() const { return this != next and next == prev; }
131 
133  bool is_unitarian_or_empty() const { return next == prev; }
134 
140  void insert(Dlink * node)
141  {
142  I((this != NULL) and (next != NULL) and (prev != NULL));
143  I(node != NULL);
144  I(node->is_empty());
145 
146  node->prev = this;
147  node->next = next;
148  next->prev = node;
149  next = node;
150  }
151 
157  void push(Dlink * node)
158  {
159  insert(node);
160  }
161 
166  void append(Dlink * node)
167  {
168  I((this != NULL) and (next != NULL) and (prev != NULL));
169  I(node != NULL);
170  I(node->is_empty());
171 
172  node->next = this;
173  node->prev = prev;
174  prev->next = node;
175  prev = node;
176  }
177 
180  {
181  I((this != NULL) and (next != NULL) and (prev != NULL));
182  return next;
183  }
184 
186  Dlink * top() { return get_next(); }
187 
190  {
191  I((this != NULL) and (next != NULL) and (prev != NULL));
192  return prev;
193  }
194 
196  Dlink *& get_first() { return next; }
197 
199  Dlink *& get_last() { return prev; }
200 
210  void insert_list(Dlink * head)
211  {
212  if (head->is_empty())
213  return;
214 
215  head->prev->next = next;
216  head->next->prev = this;
217  next->prev = head->prev;
218  next = head->next;
219  head->reset();
220  }
221 
231  void append_list(Dlink * head)
232  {
233  if (head->is_empty())
234  return;
235 
236  head->next->prev = prev;
237  head->prev->next = this;
238  prev->next = head->next;
239  prev = head->prev;
240  head->reset();
241  }
242 
252  void concat_list(Dlink * head)
253  {
254  I(head != NULL);
255 
256  if (head->is_empty())
257  return;
258 
259  if (this->is_empty())
260  {
261  swap(head);
262 
263  return;
264  }
265 
266  prev->next = head->next;
267  head->next->prev = prev;
268  prev = head->prev;
269  head->prev->next = this;
270  head->reset();
271  }
272 
273  void concat_list(Dlink & head)
274  {
275  concat_list(&head);
276  }
277 
278  void del()
279  {
280  I((this != NULL) and (next != NULL) and (prev != NULL));
281 
282  prev->next = next;
283  next->prev = prev;
284  reset();
285  }
286 
288  void erase() { del(); }
289 
297  {
298  I((this != NULL) and (next != NULL) and (prev != NULL));
299  I(prev != this);
300  I(next != this);
301 
302  Dlink* retValue = prev;
303  retValue->del();
304 
305  return retValue;
306  }
307 
309  {
310  I((this != NULL) and (next != NULL) and (prev != NULL));
311  I(prev != this);
312  I(next != this);
313 
314  Dlink* retValue = next;
315  retValue->del();
316 
317  return retValue;
318  }
319 
321  {
322  return remove_prev();
323  }
324 
326  {
327  return remove_next();
328  }
329 
330  Dlink * pop()
331  {
332  return remove_next();
333  }
334 
340  size_t reverse_list()
341  {
342  if (is_empty())
343  return 0;
344 
345  Dlink tmp; // cabecera temporal donde se guarda lista invertida
346 
347  // recorrer lista this, eliminar primero e insertar en tmp
348  size_t counter = 0;
349  for (/* nada */; not is_empty(); counter++)
350  tmp.insert(remove_next()); // eliminar e insertar en tmp
351 
352  swap(&tmp); // tmp == lista invertida; this vacía ==> swap
353 
354  return counter;
355  }
356 
372  size_t split_list(Dlink & l, Dlink & r)
373  {
374  I(l.is_empty() and r.is_empty()); // l y r deben estar vacías
375 
376  size_t count = 0;
377  while (not is_empty())
378  {
379  l.append(remove_next()); ++count;
380 
381  if (is_empty())
382  break;
383 
384  r.insert(remove_prev()); ++count;
385  }
386 
387  return count;
388  }
389 
405  {
406  I(not is_empty() and not link->is_empty() and link != this);
407 
408  Dlink list;
409  if (link == this->prev) // es link el último de la lista?
410  {
411  link->del();
412  list.append(link);
413  return list;
414  }
415 
416  if (link == this->next) // es link el primero de la lista
417  {
418  list.swap(this);
419  I(this->is_empty());
420  return list;
421  }
422 
423  list.prev = this->prev; // enlazar list a link (punto de corte)
424  list.next = link;
425  this->prev = link->prev; // quitar de this todo a partir de link
426  link->prev->next = this;
427  link->prev = &list; // colocar el corte en list
428  list.prev->next = &list;
429 
430  return list;
431  }
432 
437  class Iterator
438  {
439  private:
440 
441  mutable Dlink * head;
442  mutable Dlink * curr;
443 
444  public:
445 
447  typedef Dlink Set_Type;
448 
450  typedef Dlink * Item_Type;
451 
460  Iterator(Dlink * head_ptr) : head(head_ptr), curr(head->get_next()) {}
461 
469  Iterator(Dlink & _head) : head(&_head), curr(head->get_next())
470  {
471  // Empty
472  }
473 
485  Iterator(Dlink * head_ptr, Dlink * curr_ptr)
486  : head(head_ptr), curr(curr_ptr)
487  {
488  // Empty
489  }
490 
492  Iterator() : head(NULL), curr(NULL) { /* Empty */ }
493 
494  void reset_first()
495  {
496  I(curr != NULL and head != NULL);
497 
498  curr = head->get_next();
499  }
500 
501  void reset_last()
502  {
503  I(curr != NULL and head != NULL);
504  curr = head->get_prev();
505  }
506 
517  void set(Dlink * new_curr)
518  {
519  I(curr != NULL and head != NULL);
520  curr = new_curr;
521  }
522 
533  void reset(Dlink * new_head, Dlink * new_curr)
534  {
535  head = new_head;
536  curr = new_curr;
537  }
538 
547  void reset(Dlink * new_head)
548  {
549  head = new_head;
550  curr = head->get_next();;
551  }
552 
554  bool has_current() const
555  {
556  I(curr != NULL and head != NULL);
557  return curr != head;
558  }
559 
560  // sinónimo de has_current()
561  bool has_curr() const { return has_current(); }
562 
564  Dlink * get_current() const
565  {
566  I(curr != NULL and head != NULL);
567 
568  if (not has_current())
569  throw std::overflow_error("Not element in list");
570 
571  return curr;
572  }
573 
574  // sinónimo de get_current()
575  Dlink * get_curr() const { return get_current(); }
576 
578  bool is_in_first() const { return curr == head->next; }
579 
581  bool is_in_last() const { return curr == head->prev; }
582 
584  void prev() throw(std::exception, std::underflow_error)
585  {
586  if (not has_current())
587  throw std::underflow_error("Not previous element in list");
588 
589  curr = curr->get_prev();
590  }
591 
593  void next() throw(std::exception, std::overflow_error)
594  {
595  if (not has_current())
596  throw std::overflow_error("Not next element in list");
597 
598  curr = curr->get_next();
599  }
600 
602  bool operator == (const Iterator & it) const { return curr == it.curr; }
603 
605  bool operator != (const Iterator & it) const { return curr != it.curr; }
606 
612  Dlink * del()
613  {
614  I(curr != NULL and head != NULL);
615  I(has_current());
616 
617  Dlink * current = get_current(); // obtener nodo actual
618  next(); // avanzar al siguiente nodo
619  current->del(); // eliminar de la lista antiguo nodo actual
620  return current;
621  }
622 
623  bool verify(Dlink * l) const { return head == l; }
624 
625  bool verify(const Iterator & it) const { return head == it.head; }
626  };
627 
633  {
634  for (Iterator itor(this); itor.has_current(); delete itor.del()) ;
635  }
636 
637  bool check()
638  {
639  Iterator itor(this);
640  Dlink* node;
641 
642  for (/* nothing */; itor.has_current(); itor.next())
643  {
644  node = itor.get_current();
645 
646  if (not (node->get_next()->get_prev() == node))
647  return false;
648 
649  if (not (node->get_prev()->get_next() == node))
650  return false;
651  }
652 
653  for (itor.reset_last(); itor.has_current(); itor.prev())
654  {
655  node = itor.get_current();
656 
657  if (not (node->get_next()->get_prev() == node))
658  return false;
659 
660  if (not (node->get_prev()->get_next() == node))
661  return false;
662  }
663 
664  return true;
665  }
666 };
667 
695 # define DLINK_TO_TYPE(type_name, link_name) \
696 inline static type_name * dlink_to_##type_name(Dlink * link) \
697 { \
698  type_name * ptr_zero = 0; \
699  size_t offset_link = reinterpret_cast<size_t>(&(ptr_zero->link_name));\
700  char * address_type = reinterpret_cast<char*>(link) - offset_link; \
701  return reinterpret_cast<type_name *>(address_type); \
702 }
703 
741 # define LINKNAME_TO_TYPE(type_name, link_name) \
742 inline static type_name * link_name##_to_##type_name(Dlink * link) \
743 { \
744  type_name * ptr_zero = 0; \
745  size_t offset_link = reinterpret_cast<size_t>(&(ptr_zero->link_name));\
746  char * address_type = reinterpret_cast<char*>(link) - offset_link; \
747  return reinterpret_cast<type_name *>(address_type); \
748 }
749 
750 
779 # define DLINK_TO_BASE(type_name, link_name) \
780  inline static type_name * dlink_to_base(Dlink * link) \
781  { \
782  type_name * ptr_zero = 0; \
783  size_t offset_link = reinterpret_cast<size_t>(&(ptr_zero->link_name)); \
784  char * address_type = reinterpret_cast<char*>(link) - offset_link; \
785  return reinterpret_cast<type_name *>(address_type); \
786  }
787 
788 }
789 
790 # endif /* DLINK_H */
791 
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Definition: ahAlgo.H:127
Definition: List.H:23

Leandro Rabindranath León