Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
tpl_binHeap.H
1 
2 # ifndef TPL_BINHEAP_H
3 # define TPL_BINHEAP_H
4 
5 # include <ahDefs.H>
6 # include <ahUtils.H>
7 # include <ahFunction.H>
8 # include <tpl_binNode.H>
9 # include <tpl_dynListQueue.H>
10 
11 namespace Aleph {
12 
14 {
15  struct Control_Fields // Definición de banderas de control
16  {
17  int is_leaf : 4; // true si el nodo es hoja
18  int is_left : 4; // true si el nodo es hijo izquierdo
19  };
20 
21 
22  BinHeapNode_Data * pLink; // puntero al padre
23  Control_Fields control_fields;
24 
25 public:
26 
27  BinHeapNode_Data() : pLink(NULL)
28  {
29  control_fields.is_leaf = true;
30  control_fields.is_left = true;
31  }
32 
33  BinHeapNode_Data *& getU() { return pLink; }
34 
35  Control_Fields & get_control_fields() { return control_fields; }
36 
37  void reset()
38  {
39  control_fields.is_leaf = true;
40  control_fields.is_left = true;
41  }
42 };
43 
44 DECLARE_BINNODE(BinHeapNode, 64, BinHeapNode_Data);
45 
46 # define PREV(p) (p->getL())
47 # define NEXT(p) (p->getR())
48 # define ULINK(p) reinterpret_cast<Node*&>((p)->getU())
49 # define IS_LEAF(p) ((p)->get_control_fields().is_leaf)
50 # define IS_LEFT(p) ((p)->get_control_fields().is_left)
51 # define CTRL_BITS(p) ((p)->get_control_fields())
52 
75  template <template <class> class NodeType, typename Key,
76  class Compare = Aleph::less<Key>>
78 {
79  Compare & cmp;
80 
81 public:
82 
83  typedef NodeType<Key> Node;
84 
85  Compare & key_comp() { return cmp; }
86 
87  Compare & get_compare() { return cmp; }
88 
89 private:
90 
91  Node head_node;
92  Node * head;
93  Node *& root;
94  Node * last;
95  size_t num_nodes;
96 
97 public:
98 
99  void swap(GenBinHeap & h)
100  {
101  std::swap(root, h.root);
102  std::swap(last, h.last);
103  std::swap(num_nodes, h.num_nodes);
104  std::swap(cmp, h.cmp);
105  }
106 
107 private:
108 
109  static bool is_in_list(Node * p)
110  {
111  if (IS_LEAF(p))
112  return true;
113 
114  return ULINK(LLINK(p)) == RLINK(LLINK(p));
115  }
116 
117  static bool has_sibling(Node * p)
118  {
119  return ULINK(p) != RLINK(p);
120  }
121 
122  void swap_with_parent(Node * p)
123  {
124  I(num_nodes >= 2);
125  I(p != root);
126 
127  Node *pp = ULINK(p); // padre de p
128 
129  const bool p_has_sibling = has_sibling(p);
130  const bool p_is_in_list = is_in_list(p); // p está en último nivel?
131  const bool pp_is_in_list = is_in_list(pp); // p == last & LLINK(pp) == last?
132  const bool p_has_child = not IS_LEAF(p); // p tiene hijos?
133 
134  std::swap(CTRL_BITS(pp), CTRL_BITS(p)); // swap de banderas
135 
136  if (pp == root)
137  root = p;
138 
139  Node *ppp = ULINK(pp); // abuelo de p; padre de pp
140 
141  ULINK(pp) = p; // Actualizar ULINK
142  ULINK(p) = ppp;
143 
144  if (LLINK(ppp) == pp)
145  LLINK(ppp) = p;
146  else
147  RLINK(ppp) = p;
148 
149  Node *sp = NULL; // guarda hermano de p
150  if (p_has_sibling)
151  {
152  sp = p == LLINK(pp) ? RLINK(pp) : LLINK(pp); // hermano de p
153  I(ULINK(sp) == pp);
154  ULINK(sp) = p;
155  }
156 
157  if (p == last) // ¿actualizar last?
158  last = pp;
159 
160  if (num_nodes == 2)
161  return;
162 
163  Node *lcp = LLINK(p); // respaldo de hijos de p
164  Node *rcp = RLINK(p);
165 
166  if (num_nodes == 3)
167  {
168  if (RLINK(pp) == p)
169  {
170  LLINK(lcp) = RLINK(lcp) = pp;
171  RLINK(pp) = lcp;
172  RLINK(p) = pp;
173  }
174  else
175  {
176  LLINK(rcp) = RLINK(rcp) = pp;
177  LLINK(pp) = rcp;
178  LLINK(p) = pp;
179  }
180 
181  return;
182  }
183 
184  if (not p_is_in_list)
185  {
186  ULINK(lcp) = ULINK(rcp) = pp;
187 
188  if (LLINK(pp) == p)
189  {
190  I(RLINK(pp) == sp);
191  LLINK(p) = pp;
192  RLINK(p) = RLINK(pp);
193  }
194  else
195  {
196  I(LLINK(pp) == sp);
197  RLINK(p) = pp;
198  LLINK(p) = LLINK(pp);
199  }
200 
201  LLINK(pp) = lcp;
202  RLINK(pp) = rcp;
203 
204  return;
205  }
206 
207  if (not pp_is_in_list)
208  {
209  if (p_has_child)
210  ULINK(LLINK(p)) = pp;
211 
212  RLINK(lcp) = LLINK(rcp) = pp;
213 
214  if (LLINK(pp) == p)
215  {
216  I(RLINK(pp) == sp);
217  LLINK(p) = pp;
218  RLINK(p) = RLINK(pp);
219  }
220  else
221  {
222  I(LLINK(pp) == sp);
223  RLINK(p) = pp;
224  LLINK(p) = LLINK(pp);
225  }
226 
227  LLINK(pp) = lcp;
228  RLINK(pp) = rcp;
229 
230  return;
231  }
232 
233  RLINK(lcp) = pp;
234  LLINK(RLINK(pp)) = p;
235  LLINK(pp) = lcp;
236  RLINK(p) = RLINK(pp);
237  RLINK(pp) = p;
238  LLINK(p) = pp;
239  }
240 
241  virtual void sift_up(Node * p)
242  {
243  while (p != root and cmp (KEY(p), KEY(ULINK(p))))
244  swap_with_parent(p);
245  }
246 
247  virtual void sift_down(Node * p)
248  {
249  while (not IS_LEAF(p))
250  {
251  Node * cp = LLINK(p); // guarda el menor hijo de p
252  if (has_sibling(cp))
253  if (cmp (KEY(RLINK(p)), KEY(LLINK(p))))
254  cp = RLINK(p);
255 
256  if (cmp (KEY(p), KEY(cp)))
257  return;
258 
259  swap_with_parent(cp);
260  }
261  }
262 
263  void swap_root_with_last()
264  {
265  I(num_nodes > 1);
266  I(ULINK(root) == head);
267  I(not IS_LEAF(root));
268  I(IS_LEAF(last));
269 
270  if (num_nodes > 3) // caso general
271  {
272  Node * lRoot = LLINK(root);
273  Node * rRoot = RLINK(root);
274  Node * f_last = ULINK(last);
275  Node * prev_last = LLINK(last);
276  Node * next_last = RLINK(last);
277 
278  if (LLINK(f_last) == last)
279  LLINK(f_last) = root;
280  else
281  RLINK(f_last) = root;
282 
283  if (RLINK(root) != last)
284  std::swap(ULINK(root), ULINK(last));
285  else
286  {
287  ULINK(root) = last;
288  ULINK(root) = head;
289  }
290 
291  std::swap(LLINK(root), LLINK(last));
292  std::swap(RLINK(root), RLINK(last));
293 
294  ULINK(lRoot) = ULINK(rRoot) = last;
295 
296  LLINK(last) = lRoot;
297  RLINK(last) = rRoot;
298 
299  PREV(root) = prev_last;
300  NEXT(root) = next_last;
301 
302  NEXT(prev_last) = PREV(next_last) = root;
303  }
304  else if (num_nodes == 3) // caso particular con 3 nodos
305  {
306  I(RLINK(root) == last);
307  I(LLINK(last) == LLINK(root) and RLINK(last) == LLINK(root));
308 
309  ULINK(last) = ULINK(root);
310  ULINK(root) = last;
311 
312  Node *s_last = LLINK(last);
313  ULINK(s_last) = last;
314 
315  LLINK(last) = s_last;
316  RLINK(last) = root;
317 
318  LLINK(root) = RLINK(root) = s_last;
319  RLINK(s_last) = LLINK(s_last) = root;
320  }
321  else // casos particulares con num_nodes < 3
322  {
323  I(LLINK(root) == last);
324 
325  ULINK(last) = ULINK(root);
326  ULINK(root) = last;
327  RLINK(last) = LLINK(last) = root;
328  RLINK(root) = LLINK(root) = last;
329  }
330 
331  std::swap(CTRL_BITS(root), CTRL_BITS(last));
332  std::swap(root, last);
333  }
334 
335  Node * remove_last()
336  {
337  I(last != root and num_nodes > 0);
338  I(IS_LEAF(last));
339 
340  Node * ret_val = last;
341  Node * pp = ULINK(last);
342  Node * new_last = LLINK(last);
343 
344  if (IS_LEFT(last))
345  {
346  IS_LEAF(pp) = true;
347  LLINK(pp) = new_last;
348  }
349  else
350  {
351  RLINK(pp) = RLINK(last);
352  LLINK(RLINK(last)) = pp;
353  }
354 
355  RLINK(LLINK(last)) = pp;
356  last = new_last;
357  num_nodes--;
358  ret_val->reset();
359 
360  return ret_val;
361  }
362 
363  void replace_node(Node * node, Node * new_node)
364  {
365  I(node != new_node);
366  I(node != last);
367 
368  // guardar los parientes inmediatos de node
369  Node * parent = ULINK(node);
370  Node * left_child = LLINK(node);
371  Node * right_child = RLINK(node);
372 
373  // actualizar los punteros pertenecientes a new_node
374  ULINK(new_node) = parent;
375  LLINK(new_node) = left_child;
376  RLINK(new_node) = right_child;
377 
378  // actualizar padre
379  if (IS_LEFT(node))
380  {
381  I(LLINK(parent) == node);
382  LLINK(parent) = new_node;
383  }
384  else
385  {
386  I(RLINK(parent) == node);
387  RLINK(parent) = new_node;
388  }
389 
390  // actualizar hijos
391  if (IS_LEAF(node))
392  {
393  RLINK(left_child) = new_node;
394  LLINK(right_child) = new_node;
395  }
396  else
397  {
398  ULINK(left_child) = new_node;
399 
400  if (ULINK(right_child) == node) // node pudiera tener sólo un hijo
401  ULINK(right_child) = new_node;
402  else
403  {
404  I(left_child == last);
405  RLINK(left_child) = new_node;
406  LLINK(right_child) = new_node;
407  }
408  }
409 
410  CTRL_BITS(new_node) = CTRL_BITS(node);
411  }
412 
413  static void __postorder_delete(Node * p, Node * incomplete_node)
414  {
415  if (IS_LEAF(p))
416  {
417  delete p;
418  return;
419  }
420 
421  __postorder_delete(LLINK(p), incomplete_node);
422 
423  if (p != incomplete_node)
424  __postorder_delete(RLINK(p), incomplete_node);
425 
426  delete p;
427  }
428 
429 public:
430 
431  Node * getRoot() { return root; }
432 
433  Node * getRoot() const { return const_cast<Node*>(root); }
434 
435  template <class Op>
436  void for_each_in_preorder(Node * p, Op & op)
437  {
438  if (p == NULL)
439  return;
440 
441  op(p);
442 
443  for_each_in_preorder(advance_left(p), op);
444  for_each_in_preorder(advance_right(p), op);
445  }
446 
447  template <class Op>
448  void for_each_in_preorder(Node * p, Op && op())
449  {
450  return for_each_in_preorder<Op>(p, op);
451  }
452 
453 private:
454 
455  template <class Op>
456  bool __level_traverse(Node * root, Op & operation)
457  {
458  if (root == NULL)
459  return true;
460 
462  queue.put(root);
463 
464  while (not queue.is_empty())
465  {
466  Node * p = queue.get();
467 
468  if (not operation(p))
469  return false;
470 
471  Node * c = advance_left(p);
472  if (c == NULL)
473  continue;
474 
475  queue.put(c);
476 
477  c = advance_right(p);
478  if (c != NULL)
479  queue.put(c);
480  }
481 
482  return true;
483  }
484 
485 public:
486 
487  template <class Op>
488  bool level_traverse(Node * root, Op & operation)
489  {
490  return __level_traverse(root, operation);
491  }
492 
493  template <class Op>
494  bool level_traverse(Node * root, Op && operation = Op())
495  {
496  return __level_traverse(root, operation);
497  }
498 
499  template <class Op>
500  bool level_traverse(Node * root, Op & operation) const
501  {
502  return const_cast<GenBinHeap&>(*this).__level_traverse(root, operation);
503  }
504 
505  template <class Op>
506  bool level_traverse(Node * root, Op && operation = Op()) const
507  {
508  return const_cast<GenBinHeap&>(*this).__level_traverse(root, operation);
509  }
510 
511  GenBinHeap(Compare & __cmp)
512  : cmp(__cmp), head(&head_node), root(RLINK(head)), last(&head_node),
513  num_nodes(0)
514  {
515  // empty
516  }
517 
518  GenBinHeap(Compare && __cmp = Compare())
519  : GenBinHeap(__cmp)
520  {
521  // empty
522  }
523 
524  virtual ~GenBinHeap() { /* empty */ }
525 
533  Node * insert(Node * p)
534  {
535  I(IS_LEAF(p));
536 
537  if (root == NULL) // ¿heap está vacío?
538  { // Sí, inicialice
539 
540  I(num_nodes == 0);
541 
542  root = p;
543  LLINK(p) = RLINK(p) = p;
544  ULINK(p) = head;
545  IS_LEAF(p) = true;
546  IS_LEFT(p) = false; /* root is right child of header node */
547  last = root;
548  num_nodes = 1;
549  return p;
550  }
551  // inserción general
552  Node * pp = RLINK(last); // padre de actual last
553  LLINK(p) = last;
554  ULINK(p) = pp;
555 
556  if (IS_LEFT(last))
557  { // p será hijo derecho
558  IS_LEFT(p) = false;
559  RLINK(p) = RLINK(pp);
560  LLINK(RLINK(pp)) = p;
561  RLINK(pp) = p;
562  }
563  else
564  { // p será hijo izquierdo
565  IS_LEFT(p) = true;
566  RLINK(p) = pp;
567  IS_LEAF(pp) = false; // si p es izquierdo ==> pp era hoja
568  LLINK(pp) = p;
569  }
570 
571  I(not IS_LEAF(pp));
572 
573  RLINK(last) = p;
574  last = p;
575  num_nodes++;
576  sift_up(last);
577  return p;
578  }
579 
589  Node * getMin() throw(std::exception, std::underflow_error)
590  {
591  if (root == NULL)
592  throw std::underflow_error ("Heap is empty");
593 
594  Node *ret_val = root;
595 
596  if (num_nodes == 1)
597  {
598  root = NULL;
599  ret_val->reset();
600  num_nodes = 0;
601 
602  return ret_val;
603  }
604 
605  swap_root_with_last();
606  remove_last();
607  sift_down(root);
608  ret_val->reset();
609 
610  return ret_val;
611  }
612 
614  Node * getMax() throw(std::exception, std::underflow_error)
615  {
616  return getMin();
617  }
618 
629  void update(Node * p)
630  {
631  sift_down(p);
632  sift_up(p);
633  }
634 
644  Node * remove(Node * node) throw(std::exception, std::underflow_error)
645  {
646  if (root == NULL)
647  throw std::underflow_error ("Heap is empty");
648 
649  if (node == root)
650  return getMin();
651 
652  if (node == last)
653  return remove_last();
654 
655  Node * p = remove_last();
656 
657  if (node == last)
658  {
659  remove_last();
660  insert(p);
661 
662  return node;
663  }
664  replace_node(node, p);
665  update(p);
666  node->reset();
667 
668  return node;
669  }
670 
674  {
675  if (root == NULL)
676  return;
677 
678  if (num_nodes <= 3)
679  {
680  while (not this->is_empty())
681  delete getMin();
682  return;
683  }
684 
685  if (IS_LEFT(last))
686  __postorder_delete(root, ULINK(last));
687  else
688  __postorder_delete(root, NULL);
689 
690  root = NULL; // reiniciar como si fuese constructor
691  last = &head_node;
692  num_nodes = 0;
693  }
694 
697  Node * top() const throw(std::exception, std::underflow_error)
698  {
699  if (root == NULL)
700  throw std::underflow_error ("Heap is empty");
701 
702  return root;
703  }
704 
706  const size_t & size() const { return num_nodes; }
707 
709  bool is_empty() const { return size() == 0; }
710 
711  protected:
712 
713  Node * advance_left(Node * p)
714  {
715  if (IS_LEAF(p))
716  return NULL;
717 
718  return LLINK(p);
719  }
720 
721  Node * advance_right(Node * p)
722  {
723  I(not IS_LEAF(p));
724 
725  if (not has_sibling(LLINK(p)))
726  return NULL;
727 
728  return RLINK(p);
729  }
730 
731  virtual bool verify_heap(Node * p)
732  {
733  Node * left_link = advance_left(p);
734 
735  if (left_link == NULL)
736  {
737  I(IS_LEAF(p));
738 
739  return true;
740  }
741 
742  if (cmp (KEY(left_link), KEY(p)))
743  return false;
744 
745  Node * right_link = advance_right(p);
746 
747  if (right_link == NULL)
748  return verify_heap(left_link);
749 
750  if (cmp (KEY(right_link), KEY(p)))
751  return false;
752 
753  return verify_heap(right_link);
754  }
755 
756  public:
757 
758  bool verify_heap()
759  {
760  if (root == NULL)
761  return true;
762 
763  return verify_heap(root);
764  }
765 };
766 
783  template <class Key, typename Compare = Aleph::less<Key> >
784 struct BinHeap : public GenBinHeap<BinHeapNode, Key, Compare>
785 {
787  typedef BinHeapNode<Key> Node;
788 
790 };
791 
809  template <class Key, typename Compare = Aleph::less<Key> >
810 struct BinHeapVtl : public GenBinHeap<BinHeapNodeVtl, Key, Compare>
811 {
813  typedef BinHeapNodeVtl<Key> Node;
814 
816 };
817 
818 # undef PREV
819 # undef NEXT
820 # undef ULINK
821 # undef IS_LEAF
822 # undef IS_LEFT
823 # undef CTRL_BITS
824 } // end namespace Aleph
825 # endif // TPL_BINHEAP_H
826 
Definition: Queue.H:18
#define LLINK(p)
Definition: tpl_binNode.H:196
Node * insert(Node *p)
Definition: tpl_binHeap.H:533
#define RLINK(p)
Definition: tpl_binNode.H:201
Definition: ahFunction.H:145
Definition: tpl_binHeap.H:13
Definition: tpl_dynListQueue.H:22
Node * getMax()
Definition: tpl_binHeap.H:614
void update(Node *p)
Definition: tpl_binHeap.H:629
Definition: tpl_binHeap.H:77
Node * top() const
Definition: tpl_binHeap.H:697
Node * getMin()
Definition: tpl_binHeap.H:589
const size_t & size() const
Retorna la cardinalidad del heap.
Definition: tpl_binHeap.H:706
Definition: tpl_binHeap.H:784
Definition: tpl_binHeap.H:810
#define DECLARE_BINNODE(Name, height, Control_Data)
Definition: tpl_binNode.H:126
BinHeapNode< Key > Node
El tipo de nodo del heap.
Definition: tpl_binHeap.H:787
BinHeapNodeVtl< Key > Node
El tipo de nodo del heap.
Definition: tpl_binHeap.H:813
#define KEY(p)
Definition: tpl_binNode.H:206
T get()
Definition: tpl_dynListQueue.H:107
bool is_empty() const
Retorna true si el heap está vacío.
Definition: tpl_binHeap.H:709
void remove_all_and_delete()
Definition: tpl_binHeap.H:673
T & put(const T &data)
Definition: tpl_dynListQueue.H:86

Leandro Rabindranath León