Home | History | Annotate | Line # | Download | only in gcc
fibonacci_heap.h revision 1.3
      1  1.3  mrg /* Fibonacci heap for GNU compiler.
      2  1.3  mrg    Copyright (C) 1998-2017 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by Daniel Berlin (dan (at) cgsoftware.com).
      4  1.1  mrg    Re-implemented in C++ by Martin Liska <mliska (at) suse.cz>
      5  1.1  mrg 
      6  1.1  mrg This file is part of GCC.
      7  1.1  mrg 
      8  1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      9  1.1  mrg the terms of the GNU General Public License as published by the Free
     10  1.1  mrg Software Foundation; either version 3, or (at your option) any later
     11  1.1  mrg version.
     12  1.1  mrg 
     13  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     14  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     15  1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     16  1.1  mrg for more details.
     17  1.1  mrg 
     18  1.1  mrg You should have received a copy of the GNU General Public License
     19  1.1  mrg along with GCC; see the file COPYING3.  If not see
     20  1.1  mrg <http://www.gnu.org/licenses/>.  */
     21  1.1  mrg 
     22  1.1  mrg /* Fibonacci heaps are somewhat complex, but, there's an article in
     23  1.1  mrg    DDJ that explains them pretty well:
     24  1.1  mrg 
     25  1.1  mrg    http://www.ddj.com/articles/1997/9701/9701o/9701o.htm?topic=algoritms
     26  1.1  mrg 
     27  1.1  mrg    Introduction to algorithms by Corman and Rivest also goes over them.
     28  1.1  mrg 
     29  1.1  mrg    The original paper that introduced them is "Fibonacci heaps and their
     30  1.1  mrg    uses in improved network optimization algorithms" by Tarjan and
     31  1.1  mrg    Fredman (JACM 34(3), July 1987).
     32  1.1  mrg 
     33  1.1  mrg    Amortized and real worst case time for operations:
     34  1.1  mrg 
     35  1.1  mrg    ExtractMin: O(lg n) amortized. O(n) worst case.
     36  1.1  mrg    DecreaseKey: O(1) amortized.  O(lg n) worst case.
     37  1.1  mrg    Insert: O(1) amortized.
     38  1.1  mrg    Union: O(1) amortized.  */
     39  1.1  mrg 
     40  1.1  mrg #ifndef GCC_FIBONACCI_HEAP_H
     41  1.1  mrg #define GCC_FIBONACCI_HEAP_H
     42  1.1  mrg 
     43  1.1  mrg /* Forward definition.  */
     44  1.1  mrg 
     45  1.1  mrg template<class K, class V>
     46  1.1  mrg class fibonacci_heap;
     47  1.1  mrg 
     48  1.1  mrg /* Fibonacci heap node class.  */
     49  1.1  mrg 
     50  1.1  mrg template<class K, class V>
     51  1.1  mrg class fibonacci_node
     52  1.1  mrg {
     53  1.1  mrg   typedef fibonacci_node<K,V> fibonacci_node_t;
     54  1.1  mrg   friend class fibonacci_heap<K,V>;
     55  1.1  mrg 
     56  1.1  mrg public:
     57  1.1  mrg   /* Default constructor.  */
     58  1.1  mrg   fibonacci_node (): m_parent (NULL), m_child (NULL), m_left (this),
     59  1.1  mrg     m_right (this), m_degree (0), m_mark (0)
     60  1.1  mrg   {
     61  1.1  mrg   }
     62  1.1  mrg 
     63  1.1  mrg   /* Constructor for a node with given KEY.  */
     64  1.3  mrg   fibonacci_node (K key, V *data = NULL): m_parent (NULL), m_child (NULL),
     65  1.3  mrg     m_left (this), m_right (this), m_key (key), m_data (data),
     66  1.1  mrg     m_degree (0), m_mark (0)
     67  1.1  mrg   {
     68  1.1  mrg   }
     69  1.1  mrg 
     70  1.1  mrg   /* Compare fibonacci node with OTHER node.  */
     71  1.1  mrg   int compare (fibonacci_node_t *other)
     72  1.1  mrg   {
     73  1.1  mrg     if (m_key < other->m_key)
     74  1.1  mrg       return -1;
     75  1.1  mrg     if (m_key > other->m_key)
     76  1.1  mrg       return 1;
     77  1.1  mrg     return 0;
     78  1.1  mrg   }
     79  1.1  mrg 
     80  1.1  mrg   /* Compare the node with a given KEY.  */
     81  1.1  mrg   int compare_data (K key)
     82  1.1  mrg   {
     83  1.1  mrg     return fibonacci_node_t (key).compare (this);
     84  1.1  mrg   }
     85  1.1  mrg 
     86  1.1  mrg   /* Remove fibonacci heap node.  */
     87  1.1  mrg   fibonacci_node_t *remove ();
     88  1.1  mrg 
     89  1.1  mrg   /* Link the node with PARENT.  */
     90  1.1  mrg   void link (fibonacci_node_t *parent);
     91  1.1  mrg 
     92  1.1  mrg   /* Return key associated with the node.  */
     93  1.1  mrg   K get_key ()
     94  1.1  mrg   {
     95  1.1  mrg     return m_key;
     96  1.1  mrg   }
     97  1.1  mrg 
     98  1.1  mrg   /* Return data associated with the node.  */
     99  1.1  mrg   V *get_data ()
    100  1.1  mrg   {
    101  1.1  mrg     return m_data;
    102  1.1  mrg   }
    103  1.1  mrg 
    104  1.1  mrg private:
    105  1.1  mrg   /* Put node B after this node.  */
    106  1.1  mrg   void insert_after (fibonacci_node_t *b);
    107  1.1  mrg 
    108  1.1  mrg   /* Insert fibonacci node B after this node.  */
    109  1.1  mrg   void insert_before (fibonacci_node_t *b)
    110  1.1  mrg   {
    111  1.1  mrg     m_left->insert_after (b);
    112  1.1  mrg   }
    113  1.1  mrg 
    114  1.1  mrg   /* Parent node.  */
    115  1.1  mrg   fibonacci_node *m_parent;
    116  1.1  mrg   /* Child node.  */
    117  1.1  mrg   fibonacci_node *m_child;
    118  1.1  mrg   /* Left sibling.  */
    119  1.1  mrg   fibonacci_node *m_left;
    120  1.1  mrg   /* Right node.  */
    121  1.1  mrg   fibonacci_node *m_right;
    122  1.1  mrg   /* Key associated with node.  */
    123  1.1  mrg   K m_key;
    124  1.1  mrg   /* Data associated with node.  */
    125  1.1  mrg   V *m_data;
    126  1.1  mrg 
    127  1.1  mrg #if defined (__GNUC__) && (!defined (SIZEOF_INT) || SIZEOF_INT < 4)
    128  1.1  mrg   /* Degree of the node.  */
    129  1.1  mrg   __extension__ unsigned long int m_degree : 31;
    130  1.1  mrg   /* Mark of the node.  */
    131  1.1  mrg   __extension__ unsigned long int m_mark : 1;
    132  1.1  mrg #else
    133  1.1  mrg   /* Degree of the node.  */
    134  1.1  mrg   unsigned int m_degree : 31;
    135  1.1  mrg   /* Mark of the node.  */
    136  1.1  mrg   unsigned int m_mark : 1;
    137  1.1  mrg #endif
    138  1.1  mrg };
    139  1.1  mrg 
    140  1.1  mrg /* Fibonacci heap class. */
    141  1.1  mrg template<class K, class V>
    142  1.1  mrg class fibonacci_heap
    143  1.1  mrg {
    144  1.1  mrg   typedef fibonacci_node<K,V> fibonacci_node_t;
    145  1.1  mrg   friend class fibonacci_node<K,V>;
    146  1.1  mrg 
    147  1.1  mrg public:
    148  1.1  mrg   /* Default constructor.  */
    149  1.1  mrg   fibonacci_heap (K global_min_key): m_nodes (0), m_min (NULL), m_root (NULL),
    150  1.1  mrg     m_global_min_key (global_min_key)
    151  1.1  mrg   {
    152  1.1  mrg   }
    153  1.1  mrg 
    154  1.1  mrg   /* Destructor.  */
    155  1.1  mrg   ~fibonacci_heap ()
    156  1.1  mrg   {
    157  1.1  mrg     while (m_min != NULL)
    158  1.1  mrg       delete (extract_minimum_node ());
    159  1.1  mrg   }
    160  1.1  mrg 
    161  1.1  mrg   /* Insert new node given by KEY and DATA associated with the key.  */
    162  1.1  mrg   fibonacci_node_t *insert (K key, V *data);
    163  1.1  mrg 
    164  1.1  mrg   /* Return true if no entry is present.  */
    165  1.1  mrg   bool empty ()
    166  1.1  mrg   {
    167  1.1  mrg     return m_nodes == 0;
    168  1.1  mrg   }
    169  1.1  mrg 
    170  1.1  mrg   /* Return the number of nodes.  */
    171  1.1  mrg   size_t nodes ()
    172  1.1  mrg   {
    173  1.1  mrg     return m_nodes;
    174  1.1  mrg   }
    175  1.1  mrg 
    176  1.1  mrg   /* Return minimal key presented in the heap.  */
    177  1.1  mrg   K min_key ()
    178  1.1  mrg   {
    179  1.1  mrg     if (m_min == NULL)
    180  1.1  mrg       gcc_unreachable ();
    181  1.1  mrg 
    182  1.1  mrg     return m_min->m_key;
    183  1.1  mrg   }
    184  1.1  mrg 
    185  1.1  mrg   /* For given NODE, set new KEY value.  */
    186  1.1  mrg   K replace_key (fibonacci_node_t *node, K key)
    187  1.1  mrg   {
    188  1.1  mrg     K okey = node->m_key;
    189  1.1  mrg 
    190  1.1  mrg     replace_key_data (node, key, node->m_data);
    191  1.1  mrg     return okey;
    192  1.1  mrg   }
    193  1.1  mrg 
    194  1.1  mrg   /* For given NODE, decrease value to new KEY.  */
    195  1.1  mrg   K decrease_key (fibonacci_node_t *node, K key)
    196  1.1  mrg   {
    197  1.1  mrg     gcc_assert (key <= node->m_key);
    198  1.1  mrg     return replace_key (node, key);
    199  1.1  mrg   }
    200  1.1  mrg 
    201  1.1  mrg   /* For given NODE, set new KEY and DATA value.  */
    202  1.1  mrg   V *replace_key_data (fibonacci_node_t *node, K key, V *data);
    203  1.1  mrg 
    204  1.1  mrg   /* Extract minimum node in the heap. If RELEASE is specified,
    205  1.1  mrg      memory is released.  */
    206  1.1  mrg   V *extract_min (bool release = true);
    207  1.1  mrg 
    208  1.1  mrg   /* Return value associated with minimum node in the heap.  */
    209  1.1  mrg   V *min ()
    210  1.1  mrg   {
    211  1.1  mrg     if (m_min == NULL)
    212  1.1  mrg       return NULL;
    213  1.1  mrg 
    214  1.1  mrg     return m_min->m_data;
    215  1.1  mrg   }
    216  1.1  mrg 
    217  1.1  mrg   /* Replace data associated with NODE and replace it with DATA.  */
    218  1.1  mrg   V *replace_data (fibonacci_node_t *node, V *data)
    219  1.1  mrg   {
    220  1.1  mrg     return replace_key_data (node, node->m_key, data);
    221  1.1  mrg   }
    222  1.1  mrg 
    223  1.1  mrg   /* Delete NODE in the heap.  */
    224  1.1  mrg   V *delete_node (fibonacci_node_t *node, bool release = true);
    225  1.1  mrg 
    226  1.1  mrg   /* Union the heap with HEAPB.  */
    227  1.1  mrg   fibonacci_heap *union_with (fibonacci_heap *heapb);
    228  1.1  mrg 
    229  1.1  mrg private:
    230  1.1  mrg   /* Insert new NODE given by KEY and DATA associated with the key.  */
    231  1.1  mrg   fibonacci_node_t *insert (fibonacci_node_t *node, K key, V *data);
    232  1.1  mrg 
    233  1.3  mrg   /* Insert new NODE that has already filled key and value.  */
    234  1.3  mrg   fibonacci_node_t *insert_node (fibonacci_node_t *node);
    235  1.3  mrg 
    236  1.1  mrg   /* Insert it into the root list.  */
    237  1.1  mrg   void insert_root (fibonacci_node_t *node);
    238  1.1  mrg 
    239  1.1  mrg   /* Remove NODE from PARENT's child list.  */
    240  1.1  mrg   void cut (fibonacci_node_t *node, fibonacci_node_t *parent);
    241  1.1  mrg 
    242  1.1  mrg   /* Process cut of node Y and do it recursivelly.  */
    243  1.1  mrg   void cascading_cut (fibonacci_node_t *y);
    244  1.1  mrg 
    245  1.1  mrg   /* Extract minimum node from the heap.  */
    246  1.1  mrg   fibonacci_node_t * extract_minimum_node ();
    247  1.1  mrg 
    248  1.1  mrg   /* Remove root NODE from the heap.  */
    249  1.1  mrg   void remove_root (fibonacci_node_t *node);
    250  1.1  mrg 
    251  1.1  mrg   /* Consolidate heap.  */
    252  1.1  mrg   void consolidate ();
    253  1.1  mrg 
    254  1.1  mrg   /* Number of nodes.  */
    255  1.1  mrg   size_t m_nodes;
    256  1.1  mrg   /* Minimum node of the heap.  */
    257  1.1  mrg   fibonacci_node_t *m_min;
    258  1.1  mrg   /* Root node of the heap.  */
    259  1.1  mrg   fibonacci_node_t *m_root;
    260  1.1  mrg   /* Global minimum given in the heap construction.  */
    261  1.1  mrg   K m_global_min_key;
    262  1.1  mrg };
    263  1.1  mrg 
    264  1.1  mrg /* Remove fibonacci heap node.  */
    265  1.1  mrg 
    266  1.1  mrg template<class K, class V>
    267  1.1  mrg fibonacci_node<K,V> *
    268  1.1  mrg fibonacci_node<K,V>::remove ()
    269  1.1  mrg {
    270  1.1  mrg   fibonacci_node<K,V> *ret;
    271  1.1  mrg 
    272  1.1  mrg   if (this == m_left)
    273  1.1  mrg     ret = NULL;
    274  1.1  mrg   else
    275  1.1  mrg     ret = m_left;
    276  1.1  mrg 
    277  1.1  mrg   if (m_parent != NULL && m_parent->m_child == this)
    278  1.1  mrg     m_parent->m_child = ret;
    279  1.1  mrg 
    280  1.1  mrg   m_right->m_left = m_left;
    281  1.1  mrg   m_left->m_right = m_right;
    282  1.1  mrg 
    283  1.1  mrg   m_parent = NULL;
    284  1.1  mrg   m_left = this;
    285  1.1  mrg   m_right = this;
    286  1.1  mrg 
    287  1.1  mrg   return ret;
    288  1.1  mrg }
    289  1.1  mrg 
    290  1.1  mrg /* Link the node with PARENT.  */
    291  1.1  mrg 
    292  1.1  mrg template<class K, class V>
    293  1.1  mrg void
    294  1.1  mrg fibonacci_node<K,V>::link (fibonacci_node<K,V> *parent)
    295  1.1  mrg {
    296  1.1  mrg   if (parent->m_child == NULL)
    297  1.1  mrg     parent->m_child = this;
    298  1.1  mrg   else
    299  1.1  mrg     parent->m_child->insert_before (this);
    300  1.1  mrg   m_parent = parent;
    301  1.1  mrg   parent->m_degree++;
    302  1.1  mrg   m_mark = 0;
    303  1.1  mrg }
    304  1.1  mrg 
    305  1.1  mrg /* Put node B after this node.  */
    306  1.1  mrg 
    307  1.1  mrg template<class K, class V>
    308  1.1  mrg void
    309  1.1  mrg fibonacci_node<K,V>::insert_after (fibonacci_node<K,V> *b)
    310  1.1  mrg {
    311  1.1  mrg   fibonacci_node<K,V> *a = this;
    312  1.1  mrg 
    313  1.1  mrg   if (a == a->m_right)
    314  1.1  mrg     {
    315  1.1  mrg       a->m_right = b;
    316  1.1  mrg       a->m_left = b;
    317  1.1  mrg       b->m_right = a;
    318  1.1  mrg       b->m_left = a;
    319  1.1  mrg     }
    320  1.1  mrg   else
    321  1.1  mrg     {
    322  1.1  mrg       b->m_right = a->m_right;
    323  1.1  mrg       a->m_right->m_left = b;
    324  1.1  mrg       a->m_right = b;
    325  1.1  mrg       b->m_left = a;
    326  1.1  mrg     }
    327  1.1  mrg }
    328  1.1  mrg 
    329  1.1  mrg /* Insert new node given by KEY and DATA associated with the key.  */
    330  1.1  mrg 
    331  1.1  mrg template<class K, class V>
    332  1.1  mrg fibonacci_node<K,V>*
    333  1.1  mrg fibonacci_heap<K,V>::insert (K key, V *data)
    334  1.1  mrg {
    335  1.1  mrg   /* Create the new node.  */
    336  1.3  mrg   fibonacci_node<K,V> *node = new fibonacci_node_t (key, data);
    337  1.1  mrg 
    338  1.3  mrg   return insert_node (node);
    339  1.1  mrg }
    340  1.1  mrg 
    341  1.3  mrg /* Insert new NODE given by DATA associated with the key.  */
    342  1.1  mrg 
    343  1.1  mrg template<class K, class V>
    344  1.1  mrg fibonacci_node<K,V>*
    345  1.1  mrg fibonacci_heap<K,V>::insert (fibonacci_node_t *node, K key, V *data)
    346  1.1  mrg {
    347  1.1  mrg   /* Set the node's data.  */
    348  1.1  mrg   node->m_data = data;
    349  1.1  mrg   node->m_key = key;
    350  1.1  mrg 
    351  1.3  mrg   return insert_node (node);
    352  1.3  mrg }
    353  1.3  mrg 
    354  1.3  mrg /* Insert new NODE that has already filled key and value.  */
    355  1.3  mrg 
    356  1.3  mrg template<class K, class V>
    357  1.3  mrg fibonacci_node<K,V>*
    358  1.3  mrg fibonacci_heap<K,V>::insert_node (fibonacci_node_t *node)
    359  1.3  mrg {
    360  1.1  mrg   /* Insert it into the root list.  */
    361  1.1  mrg   insert_root (node);
    362  1.1  mrg 
    363  1.1  mrg   /* If their was no minimum, or this key is less than the min,
    364  1.1  mrg      it's the new min.  */
    365  1.1  mrg   if (m_min == NULL || node->m_key < m_min->m_key)
    366  1.1  mrg     m_min = node;
    367  1.1  mrg 
    368  1.1  mrg   m_nodes++;
    369  1.1  mrg 
    370  1.1  mrg   return node;
    371  1.1  mrg }
    372  1.1  mrg 
    373  1.1  mrg /* For given NODE, set new KEY and DATA value.  */
    374  1.3  mrg 
    375  1.1  mrg template<class K, class V>
    376  1.1  mrg V*
    377  1.1  mrg fibonacci_heap<K,V>::replace_key_data (fibonacci_node<K,V> *node, K key,
    378  1.1  mrg 				       V *data)
    379  1.1  mrg {
    380  1.1  mrg   K okey;
    381  1.1  mrg   fibonacci_node<K,V> *y;
    382  1.1  mrg   V *odata = node->m_data;
    383  1.1  mrg 
    384  1.1  mrg   /* If we wanted to, we do a real increase by redeleting and
    385  1.1  mrg      inserting.  */
    386  1.1  mrg   if (node->compare_data (key) > 0)
    387  1.1  mrg     {
    388  1.1  mrg       delete_node (node, false);
    389  1.1  mrg 
    390  1.1  mrg       node = new (node) fibonacci_node_t ();
    391  1.1  mrg       insert (node, key, data);
    392  1.1  mrg 
    393  1.1  mrg       return odata;
    394  1.1  mrg     }
    395  1.1  mrg 
    396  1.1  mrg   okey = node->m_key;
    397  1.1  mrg   node->m_data = data;
    398  1.1  mrg   node->m_key = key;
    399  1.1  mrg   y = node->m_parent;
    400  1.1  mrg 
    401  1.1  mrg   /* Short-circuit if the key is the same, as we then don't have to
    402  1.1  mrg      do anything.  Except if we're trying to force the new node to
    403  1.1  mrg      be the new minimum for delete.  */
    404  1.1  mrg   if (okey == key && okey != m_global_min_key)
    405  1.1  mrg     return odata;
    406  1.1  mrg 
    407  1.1  mrg   /* These two compares are specifically <= 0 to make sure that in the case
    408  1.1  mrg      of equality, a node we replaced the data on, becomes the new min.  This
    409  1.1  mrg      is needed so that delete's call to extractmin gets the right node.  */
    410  1.1  mrg   if (y != NULL && node->compare (y) <= 0)
    411  1.1  mrg     {
    412  1.1  mrg       cut (node, y);
    413  1.1  mrg       cascading_cut (y);
    414  1.1  mrg     }
    415  1.1  mrg 
    416  1.1  mrg   if (node->compare (m_min) <= 0)
    417  1.1  mrg     m_min = node;
    418  1.1  mrg 
    419  1.1  mrg   return odata;
    420  1.1  mrg }
    421  1.1  mrg 
    422  1.3  mrg /* Extract minimum node in the heap.  Delete fibonacci node if RELEASE
    423  1.3  mrg    is true.  */
    424  1.3  mrg 
    425  1.1  mrg template<class K, class V>
    426  1.1  mrg V*
    427  1.1  mrg fibonacci_heap<K,V>::extract_min (bool release)
    428  1.1  mrg {
    429  1.1  mrg   fibonacci_node<K,V> *z;
    430  1.1  mrg   V *ret = NULL;
    431  1.1  mrg 
    432  1.1  mrg   /* If we don't have a min set, it means we have no nodes.  */
    433  1.1  mrg   if (m_min != NULL)
    434  1.1  mrg     {
    435  1.1  mrg       /* Otherwise, extract the min node, free the node, and return the
    436  1.1  mrg        node's data.  */
    437  1.1  mrg       z = extract_minimum_node ();
    438  1.1  mrg       ret = z->m_data;
    439  1.1  mrg 
    440  1.1  mrg       if (release)
    441  1.1  mrg         delete (z);
    442  1.1  mrg     }
    443  1.1  mrg 
    444  1.1  mrg   return ret;
    445  1.1  mrg }
    446  1.1  mrg 
    447  1.1  mrg /* Delete NODE in the heap, if RELEASE is specified memory is released.  */
    448  1.1  mrg 
    449  1.1  mrg template<class K, class V>
    450  1.1  mrg V*
    451  1.1  mrg fibonacci_heap<K,V>::delete_node (fibonacci_node<K,V> *node, bool release)
    452  1.1  mrg {
    453  1.1  mrg   V *ret = node->m_data;
    454  1.1  mrg 
    455  1.1  mrg   /* To perform delete, we just make it the min key, and extract.  */
    456  1.1  mrg   replace_key (node, m_global_min_key);
    457  1.1  mrg   if (node != m_min)
    458  1.1  mrg     {
    459  1.1  mrg       fprintf (stderr, "Can't force minimum on fibheap.\n");
    460  1.1  mrg       abort ();
    461  1.1  mrg     }
    462  1.1  mrg   extract_min (release);
    463  1.1  mrg 
    464  1.1  mrg   return ret;
    465  1.1  mrg }
    466  1.1  mrg 
    467  1.3  mrg /* Union the heap with HEAPB.  One of the heaps is going to be deleted.  */
    468  1.1  mrg 
    469  1.1  mrg template<class K, class V>
    470  1.1  mrg fibonacci_heap<K,V>*
    471  1.1  mrg fibonacci_heap<K,V>::union_with (fibonacci_heap<K,V> *heapb)
    472  1.1  mrg {
    473  1.1  mrg   fibonacci_heap<K,V> *heapa = this;
    474  1.1  mrg 
    475  1.3  mrg   fibonacci_node<K,V> *a_root, *b_root;
    476  1.1  mrg 
    477  1.1  mrg   /* If one of the heaps is empty, the union is just the other heap.  */
    478  1.1  mrg   if ((a_root = heapa->m_root) == NULL)
    479  1.1  mrg     {
    480  1.1  mrg       delete (heapa);
    481  1.1  mrg       return heapb;
    482  1.1  mrg     }
    483  1.1  mrg   if ((b_root = heapb->m_root) == NULL)
    484  1.1  mrg     {
    485  1.1  mrg       delete (heapb);
    486  1.1  mrg       return heapa;
    487  1.1  mrg     }
    488  1.1  mrg 
    489  1.1  mrg   /* Merge them to the next nodes on the opposite chain.  */
    490  1.1  mrg   a_root->m_left->m_right = b_root;
    491  1.1  mrg   b_root->m_left->m_right = a_root;
    492  1.3  mrg   std::swap (a_root->m_left, b_root->m_left);
    493  1.1  mrg   heapa->m_nodes += heapb->m_nodes;
    494  1.1  mrg 
    495  1.1  mrg   /* And set the new minimum, if it's changed.  */
    496  1.3  mrg   if (heapb->m_min->compare (heapa->m_min) < 0)
    497  1.1  mrg     heapa->m_min = heapb->m_min;
    498  1.1  mrg 
    499  1.3  mrg   /* Set m_min to NULL to not to delete live fibonacci nodes.  */
    500  1.3  mrg   heapb->m_min = NULL;
    501  1.1  mrg   delete (heapb);
    502  1.3  mrg 
    503  1.1  mrg   return heapa;
    504  1.1  mrg }
    505  1.1  mrg 
    506  1.1  mrg /* Insert it into the root list.  */
    507  1.1  mrg 
    508  1.1  mrg template<class K, class V>
    509  1.1  mrg void
    510  1.1  mrg fibonacci_heap<K,V>::insert_root (fibonacci_node_t *node)
    511  1.1  mrg {
    512  1.1  mrg   /* If the heap is currently empty, the new node becomes the singleton
    513  1.1  mrg      circular root list.  */
    514  1.1  mrg   if (m_root == NULL)
    515  1.1  mrg     {
    516  1.1  mrg       m_root = node;
    517  1.1  mrg       node->m_left = node;
    518  1.1  mrg       node->m_right = node;
    519  1.1  mrg       return;
    520  1.1  mrg     }
    521  1.1  mrg 
    522  1.1  mrg   /* Otherwise, insert it in the circular root list between the root
    523  1.1  mrg      and it's right node.  */
    524  1.1  mrg   m_root->insert_after (node);
    525  1.1  mrg }
    526  1.1  mrg 
    527  1.1  mrg /* Remove NODE from PARENT's child list.  */
    528  1.1  mrg 
    529  1.1  mrg template<class K, class V>
    530  1.1  mrg void
    531  1.1  mrg fibonacci_heap<K,V>::cut (fibonacci_node<K,V> *node,
    532  1.1  mrg 			  fibonacci_node<K,V> *parent)
    533  1.1  mrg {
    534  1.1  mrg   node->remove ();
    535  1.1  mrg   parent->m_degree--;
    536  1.1  mrg   insert_root (node);
    537  1.1  mrg   node->m_parent = NULL;
    538  1.1  mrg   node->m_mark = 0;
    539  1.1  mrg }
    540  1.1  mrg 
    541  1.1  mrg /* Process cut of node Y and do it recursivelly.  */
    542  1.1  mrg 
    543  1.1  mrg template<class K, class V>
    544  1.1  mrg void
    545  1.1  mrg fibonacci_heap<K,V>::cascading_cut (fibonacci_node<K,V> *y)
    546  1.1  mrg {
    547  1.1  mrg   fibonacci_node<K,V> *z;
    548  1.1  mrg 
    549  1.1  mrg   while ((z = y->m_parent) != NULL)
    550  1.1  mrg     {
    551  1.1  mrg       if (y->m_mark == 0)
    552  1.1  mrg 	{
    553  1.1  mrg 	  y->m_mark = 1;
    554  1.1  mrg 	  return;
    555  1.1  mrg 	}
    556  1.1  mrg       else
    557  1.1  mrg 	{
    558  1.1  mrg 	  cut (y, z);
    559  1.1  mrg 	  y = z;
    560  1.1  mrg 	}
    561  1.1  mrg     }
    562  1.1  mrg }
    563  1.1  mrg 
    564  1.1  mrg /* Extract minimum node from the heap.  */
    565  1.3  mrg 
    566  1.1  mrg template<class K, class V>
    567  1.1  mrg fibonacci_node<K,V>*
    568  1.1  mrg fibonacci_heap<K,V>::extract_minimum_node ()
    569  1.1  mrg {
    570  1.1  mrg   fibonacci_node<K,V> *ret = m_min;
    571  1.1  mrg   fibonacci_node<K,V> *x, *y, *orig;
    572  1.1  mrg 
    573  1.1  mrg   /* Attach the child list of the minimum node to the root list of the heap.
    574  1.1  mrg      If there is no child list, we don't do squat.  */
    575  1.1  mrg   for (x = ret->m_child, orig = NULL; x != orig && x != NULL; x = y)
    576  1.1  mrg     {
    577  1.1  mrg       if (orig == NULL)
    578  1.1  mrg 	orig = x;
    579  1.1  mrg       y = x->m_right;
    580  1.1  mrg       x->m_parent = NULL;
    581  1.1  mrg       insert_root (x);
    582  1.1  mrg     }
    583  1.1  mrg 
    584  1.1  mrg   /* Remove the old root.  */
    585  1.1  mrg   remove_root (ret);
    586  1.1  mrg   m_nodes--;
    587  1.1  mrg 
    588  1.1  mrg   /* If we are left with no nodes, then the min is NULL.  */
    589  1.1  mrg   if (m_nodes == 0)
    590  1.1  mrg     m_min = NULL;
    591  1.1  mrg   else
    592  1.1  mrg     {
    593  1.1  mrg       /* Otherwise, consolidate to find new minimum, as well as do the reorg
    594  1.1  mrg        work that needs to be done.  */
    595  1.1  mrg       m_min = ret->m_right;
    596  1.1  mrg       consolidate ();
    597  1.1  mrg     }
    598  1.1  mrg 
    599  1.1  mrg   return ret;
    600  1.1  mrg }
    601  1.1  mrg 
    602  1.1  mrg /* Remove root NODE from the heap.  */
    603  1.1  mrg 
    604  1.1  mrg template<class K, class V>
    605  1.1  mrg void
    606  1.1  mrg fibonacci_heap<K,V>::remove_root (fibonacci_node<K,V> *node)
    607  1.1  mrg {
    608  1.1  mrg   if (node->m_left == node)
    609  1.1  mrg     m_root = NULL;
    610  1.1  mrg   else
    611  1.1  mrg     m_root = node->remove ();
    612  1.1  mrg }
    613  1.1  mrg 
    614  1.1  mrg /* Consolidate heap.  */
    615  1.1  mrg 
    616  1.1  mrg template<class K, class V>
    617  1.1  mrg void fibonacci_heap<K,V>::consolidate ()
    618  1.1  mrg {
    619  1.1  mrg   int D = 1 + 8 * sizeof (long);
    620  1.1  mrg   auto_vec<fibonacci_node<K,V> *> a (D);
    621  1.1  mrg   a.safe_grow_cleared (D);
    622  1.1  mrg   fibonacci_node<K,V> *w, *x, *y;
    623  1.1  mrg   int i, d;
    624  1.1  mrg 
    625  1.1  mrg   while ((w = m_root) != NULL)
    626  1.1  mrg     {
    627  1.1  mrg       x = w;
    628  1.1  mrg       remove_root (w);
    629  1.1  mrg       d = x->m_degree;
    630  1.1  mrg       while (a[d] != NULL)
    631  1.1  mrg 	{
    632  1.1  mrg 	  y = a[d];
    633  1.1  mrg 	  if (x->compare (y) > 0)
    634  1.1  mrg 	    std::swap (x, y);
    635  1.1  mrg 	  y->link (x);
    636  1.1  mrg 	  a[d] = NULL;
    637  1.1  mrg 	  d++;
    638  1.1  mrg 	}
    639  1.1  mrg       a[d] = x;
    640  1.1  mrg     }
    641  1.1  mrg   m_min = NULL;
    642  1.1  mrg   for (i = 0; i < D; i++)
    643  1.1  mrg     if (a[i] != NULL)
    644  1.1  mrg       {
    645  1.1  mrg 	insert_root (a[i]);
    646  1.1  mrg 	if (m_min == NULL || a[i]->compare (m_min) < 0)
    647  1.1  mrg 	  m_min = a[i];
    648  1.1  mrg       }
    649  1.1  mrg }
    650  1.1  mrg 
    651  1.1  mrg #endif  // GCC_FIBONACCI_HEAP_H
    652