tpl_binHeap.H

00001 
00002 /*
00003   This file is part of Aleph system
00004 
00005   Copyright (c) 2002, 2003, 2004, 2005, 2006
00006   UNIVERSITY LOS ANDES (ULA) Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA  
00007 
00008   - Center of Studies in Microelectronics & Distributed Systems (CEMISID) 
00009   - ULA Computer Science Department
00010   - FUNDACITE Mérida - Ministerio de Ciencia y Tecnología
00011 
00012   PERMISSION TO USE, COPY, MODIFY AND DISTRIBUTE THIS SOFTWARE AND ITS
00013   DOCUMENTATION IS HEREBY GRANTED, PROVIDED THAT BOTH THE COPYRIGHT
00014   NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES OF THE
00015   SOFTWARE, DERIVATIVE WORKS OR MODIFIED VERSIONS, AND ANY PORTIONS
00016   THEREOF, AND THAT BOTH NOTICES APPEAR IN SUPPORTING DOCUMENTATION.
00017 
00018   Aleph is distributed in the hope that it will be useful, but WITHOUT
00019   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00020   or FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022   UNIVERSIDAD DE LOS ANDES requests users of this software to return to 
00023 
00024   Leandro Leon
00025   CEMISID 
00026   Ed La Hechicera 
00027   3er piso, ala sur
00028   Facultad de Ingenieria 
00029   Universidad de Los Andes 
00030   Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA    or
00031 
00032   lrleon@ula.ve
00033 
00034   any improvements or extensions that they make and grant Universidad 
00035   de Los Andes (ULA) the rights to redistribute these changes. 
00036 
00037   Aleph is (or was) granted by: 
00038   - Consejo de Desarrollo Cientifico, Humanistico, Tecnico de la ULA 
00039     (CDCHT)
00040   - Fundacite Mérida
00041 */
00042 
00043 
00044 # ifndef TPL_BINHEAP_H
00045 # define TPL_BINHEAP_H
00046 
00047 # include <ahDefs.H>
00048 # include <ahUtils.H>
00049 # include <ahFunction.H>
00050 # include <tpl_binNode.H>
00051 
00052 namespace Aleph {
00053 
00054 class BinHeapNode_Data
00055 {
00056   struct Control_Fields // Definición de banderas de control
00057   {
00058     int is_leaf : 4; // true si el nodo es hoja
00059     int is_left : 4; // true si el nodo es hijo izquierdo
00060   };
00061 
00062   BinHeapNode_Data * pLink; // puntero al padre
00063 
00064   Control_Fields control_fields;
00065 
00066 public:
00067 
00068 
00069   BinHeapNode_Data() : pLink(NULL)
00070   { 
00071     control_fields.is_leaf = true;
00072     control_fields.is_left = true;
00073   }
00074 
00075   BinHeapNode_Data *& getU() { return pLink; }
00076 
00077   Control_Fields & get_control_fields() { return control_fields; }
00078 
00079   void reset()
00080   {
00081     control_fields.is_leaf = true;
00082     control_fields.is_left = true;
00083   }
00084 };
00085 
00086 DECLARE_BINNODE(BinHeapNode, 64, BinHeapNode_Data);
00087 
00088 
00089 # define PREV(p)      (p->getL())
00090 # define NEXT(p)      (p->getR())
00091 # define ULINK(p)     reinterpret_cast<Node*&>((p)->getU())
00092 # define IS_LEAF(p)   ((p)->get_control_fields().is_leaf)
00093 # define IS_LEFT(p)   ((p)->get_control_fields().is_left)
00094 # define CTRL_BITS(p) ((p)->get_control_fields())
00095 
00118     template <template <class> class NodeType, 
00119               typename Key, 
00120               class Compare = Aleph::less<Key> >
00121 class GenBinHeap
00122 {
00123 
00124 public:
00125 
00126   typedef NodeType<Key> Node;
00127 
00128 private:
00129 
00130     Node     head_node;
00131     Node *   head;
00132     Node *&  root;
00133     Node *   last;
00134     size_t   num_nodes;
00135   static bool is_in_list(Node * p)
00136   {
00137     if (IS_LEAF(p))
00138       return true;
00139 
00140     return ULINK(LLINK(p)) == RLINK(LLINK(p));
00141   }
00142   static bool has_sibling(Node * p)
00143   {
00144     return ULINK(p) != RLINK(p);
00145   }
00146   void swap_with_parent(Node * p)
00147   {
00148     I(num_nodes >= 2);
00149 
00150     Node *pp = ULINK(p); // padre de p
00151 
00152     const bool p_has_sibling = has_sibling(p); 
00153     const bool p_is_in_list  = is_in_list(p);  // ¿p está en último nivel?
00154     const bool pp_is_in_list = is_in_list(pp); // ¿p == last & LLINK(pp) == last?
00155     const bool p_has_child   = not IS_LEAF(p); // ¿p tiene hijos?
00156 
00157     Aleph::swap(CTRL_BITS(pp), CTRL_BITS(p)); // swap de banderas
00158 
00159     Node *ppp = ULINK(pp); // abuelo de p; padre de pp
00160 
00161     ULINK(pp) = p;  // Actualizar ULINK
00162     ULINK(p) = ppp;
00163 
00164     if (LLINK(ppp) == pp)
00165       LLINK(ppp) = p;
00166     else
00167       RLINK(ppp) = p;
00168 
00169     Node *sp = NULL;  // guarda hermano de p
00170     if (p_has_sibling) 
00171       {
00172         sp = p == LLINK(pp) ? RLINK(pp) : LLINK(pp); // hermano de p
00173         I(ULINK(sp) == pp);
00174         ULINK(sp) = p;
00175       }
00176 
00177     if (p == last) // ¿actualizar last?
00178       last = pp;
00179     
00180     if (num_nodes == 2)
00181       return;
00182 
00183     Node *lcp = LLINK(p); // respaldo de hijos de p
00184     Node *rcp = RLINK(p);
00185    
00186     if (num_nodes == 3)
00187       {
00188         if (RLINK(pp) == p)
00189           {
00190             LLINK(lcp) = RLINK(lcp) = pp;
00191             RLINK(pp)  = lcp;
00192             RLINK(p)   = pp;
00193           }
00194         else
00195           {
00196             LLINK(rcp) = RLINK(rcp) = pp;
00197             LLINK(pp)  = rcp;
00198             LLINK(p)   = pp;
00199           }
00200 
00201         return;
00202       }
00203 
00204     if (not p_is_in_list)
00205       {
00206         ULINK(lcp) = ULINK(rcp) = pp;
00207 
00208         if (LLINK(pp) == p)
00209           {
00210             I(RLINK(pp) == sp);
00211             LLINK(p) = pp;
00212             RLINK(p) = RLINK(pp);
00213           }
00214         else
00215           {
00216             I(LLINK(pp) == sp);
00217             RLINK(p) = pp;
00218             LLINK(p) = LLINK(pp);
00219           }
00220 
00221         LLINK(pp) = lcp;
00222         RLINK(pp) = rcp;
00223 
00224         return;
00225       }
00226       
00227     if (not pp_is_in_list)
00228       {
00229         if (p_has_child)
00230           ULINK(LLINK(p)) = pp;
00231 
00232         RLINK(lcp) = LLINK(rcp) = pp;
00233 
00234         if (LLINK(pp) == p)
00235           {
00236             I(RLINK(pp) == sp);
00237             LLINK(p) = pp;
00238             RLINK(p) = RLINK(pp);
00239           }
00240         else
00241           {
00242             I(LLINK(pp) == sp);
00243             RLINK(p)  = pp;
00244             LLINK(p)  = LLINK(pp);
00245           }
00246 
00247         LLINK(pp) = lcp;
00248         RLINK(pp) = rcp;
00249 
00250         return;
00251       }
00252       
00253     RLINK(lcp)       = pp;
00254     LLINK(RLINK(pp)) = p;
00255     LLINK(pp)        = lcp;
00256     RLINK(p)         = RLINK(pp);
00257     RLINK(pp)        = p;
00258     LLINK(p)         = pp;
00259   }
00260   virtual void sift_up(Node * p)
00261   {
00262     while (p != root and Compare() (KEY(p), KEY(ULINK(p))))
00263       swap_with_parent(p);
00264   }
00265 
00266   virtual void sift_down(Node * p)
00267   {
00268     Node *cp; // guarda el menor hijo de p
00269 
00270     while (not IS_LEAF(p))
00271       {
00272         cp = LLINK(p); 
00273         
00274         if (has_sibling(cp))
00275           if (Compare() (KEY(RLINK(p)), KEY(LLINK(p))))
00276             cp = RLINK(p);
00277           
00278         if (Compare() (KEY(p), KEY(cp)))
00279           return;
00280 
00281         swap_with_parent(cp);
00282       }
00283   }
00284   void swap_root_with_last()
00285   {
00286     I(num_nodes > 1);
00287     I(ULINK(root) == head);
00288     I(not IS_LEAF(root));
00289     I(IS_LEAF(last));
00290 
00291     if (num_nodes > 3) // caso general
00292       {
00293         Node * lRoot     = LLINK(root);
00294         Node * rRoot     = RLINK(root);
00295         Node * f_last    = ULINK(last);
00296         Node * prev_last = LLINK(last);
00297         Node * next_last = RLINK(last);
00298 
00299         if (LLINK(f_last) == last)
00300           LLINK(f_last) = root;
00301         else
00302           RLINK(f_last) = root;       
00303           
00304         if (RLINK(root) != last)
00305           Aleph::swap(ULINK(root), ULINK(last));
00306         else
00307           {
00308             ULINK(root) = last;
00309             ULINK(root) = head;
00310           }
00311 
00312         Aleph::swap(LLINK(root), LLINK(last));
00313         Aleph::swap(RLINK(root), RLINK(last));
00314         
00315         ULINK(lRoot) = ULINK(rRoot) = last;
00316 
00317         LLINK(last) = lRoot;
00318         RLINK(last) = rRoot;
00319 
00320         PREV(root) = prev_last;
00321         NEXT(root) = next_last;
00322 
00323         NEXT(prev_last) = PREV(next_last) = root;
00324       }      
00325     else if (num_nodes == 3) // caso particular con 3 nodos
00326       {
00327         I(RLINK(root) == last);
00328         I(LLINK(last) == LLINK(root) and RLINK(last) == LLINK(root));
00329 
00330         ULINK(last) = ULINK(root);
00331         ULINK(root) = last;
00332 
00333         Node *s_last  = LLINK(last);
00334         ULINK(s_last) = last;
00335 
00336         LLINK(last) = s_last;
00337         RLINK(last) = root;
00338 
00339         LLINK(root) = RLINK(root) = s_last;
00340         RLINK(s_last) = LLINK(s_last) = root;
00341       }
00342     else // casos particulares con num_nodes < 3
00343       {
00344         I(LLINK(root) == last);
00345 
00346         ULINK(last) = ULINK(root);
00347         ULINK(root) = last;
00348         RLINK(last) = LLINK(last) = root;
00349         RLINK(root) = LLINK(root) = last;
00350       }
00351 
00352     Aleph::swap(CTRL_BITS(root), CTRL_BITS(last));
00353     Aleph::swap(root, last);
00354   }
00355   Node * remove_last()
00356   {
00357 
00358     I(last != root and num_nodes > 0);
00359     I(IS_LEAF(last));
00360 
00361     Node * ret_val  = last;
00362     Node * pp       = ULINK(last);
00363     Node * new_last = LLINK(last);
00364 
00365     if (IS_LEFT(last))
00366       {
00367         IS_LEAF(pp) = true;
00368         LLINK(pp)   = new_last;
00369       }
00370     else
00371       {
00372         RLINK(pp)          = RLINK(last);
00373         LLINK(RLINK(last)) = pp;
00374       }
00375 
00376     RLINK(LLINK(last)) = pp;
00377     last = new_last;
00378 
00379     num_nodes--;
00380 
00381     ret_val->reset();
00382 
00383     return ret_val;
00384   }
00385   void replace_node(Node * node, Node * new_node)
00386   {
00387     I(node != new_node);
00388     I(node != last);
00389 
00390         // guardar los parientes inmediatos de node
00391     Node * parent = ULINK(node);
00392     Node * left_child  = LLINK(node);
00393     Node * right_child = RLINK(node);
00394       
00395         // actualizar los punteros pertenecientes a new_node
00396     ULINK(new_node) = parent;
00397     LLINK(new_node) = left_child;
00398     RLINK(new_node) = right_child;
00399 
00400         // actualizar padre
00401     if (IS_LEFT(node))
00402       {
00403         I(LLINK(parent) == node);
00404         LLINK(parent) = new_node;
00405       }
00406     else 
00407       {
00408         I(RLINK(parent) == node);
00409         RLINK(parent) = new_node;
00410       }
00411 
00412         // actualizar hijos
00413     if (IS_LEAF(node))
00414       {
00415         RLINK(left_child)  = new_node;
00416         LLINK(right_child) = new_node;
00417       }
00418     else 
00419       {
00420         ULINK(left_child) = new_node;
00421 
00422         if (ULINK(right_child) == node) // node pudiera tener sólo un hijo
00423           ULINK(right_child) = new_node;
00424         else
00425           {
00426             I(left_child == last);
00427             RLINK(left_child)  = new_node;
00428             LLINK(right_child) = new_node;
00429           }
00430       }
00431       
00432     CTRL_BITS(new_node) = CTRL_BITS(node);
00433   }
00434   static void __postorder_delete(Node * p, Node * incomplete_node)
00435   {
00436     if (IS_LEAF(p))
00437       {
00438         delete p;
00439 
00440         return;
00441       }
00442 
00443     __postorder_delete(LLINK(p), incomplete_node);
00444 
00445     if (p != incomplete_node)
00446       __postorder_delete(RLINK(p), incomplete_node); 
00447 
00448     delete p;
00449   }
00450 
00451 public:
00452 
00453   GenBinHeap() 
00454     : head(&head_node), root(RLINK(head)), last(&head_node), num_nodes(0)
00455   { /* empty */ }
00456 
00457   virtual ~GenBinHeap() { /* Empty */ }
00465   Node * insert(Node * p)
00466   {
00467 
00468     I(IS_LEAF(p));
00469 
00470     if (root == NULL) // ¿heap está vacío?
00471       { // Sí, inicialice
00472 
00473         I(num_nodes == 0);
00474 
00475         root       = p;
00476         LLINK(p)   = RLINK(p) = p;
00477         ULINK(p)   = head;
00478         IS_LEAF(p) = true;
00479         IS_LEFT(p) = false; /* root is right child of header node */
00480         last      = root;
00481         num_nodes = 1;
00482 
00483         return p;
00484       }
00485 
00486      // inserción general
00487 
00488     Node * pp = RLINK(last); // padre de actual last
00489 
00490     LLINK(p) = last;
00491     ULINK(p) = pp;
00492       
00493     if (IS_LEFT(last)) 
00494       { // p será hijo derecho
00495         IS_LEFT(p)       = false;
00496         RLINK(p)         = RLINK(pp);
00497         LLINK(RLINK(pp)) = p;
00498         RLINK(pp)        = p;
00499       }
00500     else
00501       { // p será hijo izquierdo
00502         IS_LEFT(p) = true;
00503         RLINK(p)   = pp;
00504         IS_LEAF(pp) = false; // si p es izquierdo ==> pp era hoja
00505         LLINK(pp)   = p;
00506       }
00507 
00508 
00509     I(not IS_LEAF(pp));
00510 
00511     RLINK(last) = p;
00512     last        = p;
00513 
00514     num_nodes++;
00515 
00516     sift_up(last);
00517 
00518     return p;
00519   }
00529   Node * getMin() 
00530 
00531     throw(std::exception, std::underflow_error)
00532 
00533   {
00534 
00535     if (root == NULL)
00536       throw std::underflow_error ("Heap is empty");
00537 
00538     Node *ret_val = root;
00539 
00540     if (num_nodes == 1)
00541       {
00542         root = NULL;
00543         ret_val->reset();
00544         num_nodes = 0;
00545         return ret_val;
00546       }
00547 
00548     swap_root_with_last();
00549 
00550     remove_last();
00551 
00552     sift_down(root);
00553 
00554     ret_val->reset();
00555 
00556     return ret_val;
00557   }
00568   void update(Node * p)
00569   {
00570     sift_down(p);
00571     sift_up(p);
00572   }
00582   Node * remove(Node * node) throw(std::exception, std::underflow_error)
00583   {
00584 
00585     if (root == NULL)
00586       throw std::underflow_error ("Heap is empty");
00587 
00588     if (node == root)
00589       return getMin();
00590 
00591     if (node == last)
00592       return remove_last();
00593 
00594     Node * p = remove_last();
00595 
00596     if (node == last)
00597       {
00598         remove_last();
00599         insert(p);
00600 
00601         return node;
00602       }
00603 
00604     replace_node(node, p);
00605 
00606     update(p);
00607 
00608     node->reset();
00609 
00610     return node;
00611   }
00614   void remove_all_and_delete()
00615   {
00616     if (root == NULL)
00617       return;
00618 
00619     if (num_nodes <= 3)
00620       {
00621         while (not this->is_empty()) 
00622           delete getMin(); 
00623 
00624         return;
00625       }
00626 
00627     if (IS_LEFT(last))
00628       __postorder_delete(root, ULINK(last));
00629     else
00630       __postorder_delete(root, NULL);
00631 
00632         // reiniciar como si se hubiese llamado a constructor
00633     root = NULL;
00634     last = &head_node;
00635     num_nodes = 0;
00636   }
00639   Node * top() const throw(std::exception, std::underflow_error)
00640   {
00641     if (root == NULL)
00642       throw std::underflow_error ("Heap is empty");
00643 
00644     return root;
00645   }
00647   const size_t & size() const { return num_nodes; }
00648 
00650   bool is_empty() const { return size() == 0; }
00651   protected:
00652 
00653   Node * advance_left(Node * p)
00654   {
00655     if (IS_LEAF(p))
00656       return NULL;
00657 
00658     return LLINK(p);
00659   }
00660 
00661   Node * advance_right(Node * p)
00662   {
00663     I(not IS_LEAF(p));
00664 
00665     if (not has_sibling(LLINK(p)))
00666       return NULL;
00667 
00668     return RLINK(p);
00669   }
00670 
00671   virtual bool verify_heap(Node * p)
00672   {
00673     Node * left_link = advance_left(p);
00674 
00675     if (left_link == NULL)
00676       {
00677         I(IS_LEAF(p));
00678 
00679         return true;
00680       }
00681 
00682     if (Compare () (KEY(left_link), KEY(p)))
00683       return false;
00684 
00685     Node * right_link = advance_right(p);
00686 
00687     if (right_link == NULL)
00688       return verify_heap(left_link);
00689 
00690     if (Compare () (KEY(right_link), KEY(p)))
00691       return false;
00692 
00693     return verify_heap(right_link);
00694   }
00695 
00696   public:
00697 
00698   bool verify_heap()
00699   {
00700     if (root == NULL)
00701       return true;
00702 
00703     return verify_heap(root);
00704   }
00705 };
00706 
00723     template <class Key, typename Compare = Aleph::less<Key> >
00724 class BinHeap : public GenBinHeap<BinHeapNode, Key, Compare>
00725 {
00726 
00727 public:
00728 
00730   typedef BinHeapNode<Key> Node;
00731 };
00732  
00750     template <class Key, typename Compare = Aleph::less<Key> >
00751 class BinHeapVtl : public GenBinHeap<BinHeapNodeVtl, Key, Compare>
00752 {
00753 
00754 public:
00755 
00757   typedef BinHeapNodeVtl<Key> Node;
00758 };
00759 
00760 # undef PREV
00761 # undef NEXT
00762 # undef ULINK
00763 # undef IS_LEAF
00764 # undef IS_LEFT
00765 # undef CTRL_BITS
00766 
00767 } // end namespace Aleph
00768 # endif //  TPL_BINHEAP_H
00769 

Leandro R. León