Home | History | Annotate | Line # | Download | only in gcc
fibonacci_heap.h revision 1.6
      1  1.3  mrg /* Fibonacci heap for GNU compiler.
      2  1.6  mrg    Copyright (C) 1998-2020 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.6  mrg     m_right (this), m_data (NULL), 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.6  mrg   /* Default constructor.  ALLOCATOR is optional and is primarily useful
    149  1.6  mrg      when heaps are going to be merged (in that case they need to be allocated
    150  1.6  mrg      in same alloc pool).  */
    151  1.6  mrg   fibonacci_heap (K global_min_key, pool_allocator *allocator = NULL):
    152  1.6  mrg     m_nodes (0), m_min (NULL), m_root (NULL),
    153  1.6  mrg     m_global_min_key (global_min_key),
    154  1.6  mrg     m_allocator (allocator), m_own_allocator (false)
    155  1.1  mrg   {
    156  1.6  mrg     if (!m_allocator)
    157  1.6  mrg       {
    158  1.6  mrg 	m_allocator = new pool_allocator ("Fibonacci heap",
    159  1.6  mrg 					    sizeof (fibonacci_node_t));
    160  1.6  mrg 	m_own_allocator = true;
    161  1.6  mrg       }
    162  1.1  mrg   }
    163  1.1  mrg 
    164  1.1  mrg   /* Destructor.  */
    165  1.1  mrg   ~fibonacci_heap ()
    166  1.1  mrg   {
    167  1.6  mrg     /* Actual memory will be released by the destructor of m_allocator.  */
    168  1.6  mrg     if (need_finalization_p<fibonacci_node_t> () || !m_own_allocator)
    169  1.6  mrg       while (m_min != NULL)
    170  1.6  mrg 	{
    171  1.6  mrg 	  fibonacci_node_t *n = extract_minimum_node ();
    172  1.6  mrg 	  n->~fibonacci_node_t ();
    173  1.6  mrg 	  if (!m_own_allocator)
    174  1.6  mrg 	    m_allocator->remove (n);
    175  1.6  mrg 	}
    176  1.6  mrg     if (m_own_allocator)
    177  1.6  mrg       delete m_allocator;
    178  1.1  mrg   }
    179  1.1  mrg 
    180  1.1  mrg   /* Insert new node given by KEY and DATA associated with the key.  */
    181  1.1  mrg   fibonacci_node_t *insert (K key, V *data);
    182  1.1  mrg 
    183  1.1  mrg   /* Return true if no entry is present.  */
    184  1.6  mrg   bool empty () const
    185  1.1  mrg   {
    186  1.1  mrg     return m_nodes == 0;
    187  1.1  mrg   }
    188  1.1  mrg 
    189  1.1  mrg   /* Return the number of nodes.  */
    190  1.6  mrg   size_t nodes () const
    191  1.1  mrg   {
    192  1.1  mrg     return m_nodes;
    193  1.1  mrg   }
    194  1.1  mrg 
    195  1.1  mrg   /* Return minimal key presented in the heap.  */
    196  1.6  mrg   K min_key () const
    197  1.1  mrg   {
    198  1.1  mrg     if (m_min == NULL)
    199  1.1  mrg       gcc_unreachable ();
    200  1.1  mrg 
    201  1.1  mrg     return m_min->m_key;
    202  1.1  mrg   }
    203  1.1  mrg 
    204  1.1  mrg   /* For given NODE, set new KEY value.  */
    205  1.1  mrg   K replace_key (fibonacci_node_t *node, K key)
    206  1.1  mrg   {
    207  1.1  mrg     K okey = node->m_key;
    208  1.1  mrg 
    209  1.1  mrg     replace_key_data (node, key, node->m_data);
    210  1.1  mrg     return okey;
    211  1.1  mrg   }
    212  1.1  mrg 
    213  1.1  mrg   /* For given NODE, decrease value to new KEY.  */
    214  1.1  mrg   K decrease_key (fibonacci_node_t *node, K key)
    215  1.1  mrg   {
    216  1.1  mrg     gcc_assert (key <= node->m_key);
    217  1.1  mrg     return replace_key (node, key);
    218  1.1  mrg   }
    219  1.1  mrg 
    220  1.1  mrg   /* For given NODE, set new KEY and DATA value.  */
    221  1.1  mrg   V *replace_key_data (fibonacci_node_t *node, K key, V *data);
    222  1.1  mrg 
    223  1.1  mrg   /* Extract minimum node in the heap. If RELEASE is specified,
    224  1.1  mrg      memory is released.  */
    225  1.1  mrg   V *extract_min (bool release = true);
    226  1.1  mrg 
    227  1.1  mrg   /* Return value associated with minimum node in the heap.  */
    228  1.6  mrg   V *min () const
    229  1.1  mrg   {
    230  1.1  mrg     if (m_min == NULL)
    231  1.1  mrg       return NULL;
    232  1.1  mrg 
    233  1.1  mrg     return m_min->m_data;
    234  1.1  mrg   }
    235  1.1  mrg 
    236  1.1  mrg   /* Replace data associated with NODE and replace it with DATA.  */
    237  1.1  mrg   V *replace_data (fibonacci_node_t *node, V *data)
    238  1.1  mrg   {
    239  1.1  mrg     return replace_key_data (node, node->m_key, data);
    240  1.1  mrg   }
    241  1.1  mrg 
    242  1.1  mrg   /* Delete NODE in the heap.  */
    243  1.1  mrg   V *delete_node (fibonacci_node_t *node, bool release = true);
    244  1.1  mrg 
    245  1.1  mrg   /* Union the heap with HEAPB.  */
    246  1.1  mrg   fibonacci_heap *union_with (fibonacci_heap *heapb);
    247  1.1  mrg 
    248  1.1  mrg private:
    249  1.1  mrg   /* Insert new NODE given by KEY and DATA associated with the key.  */
    250  1.1  mrg   fibonacci_node_t *insert (fibonacci_node_t *node, K key, V *data);
    251  1.1  mrg 
    252  1.3  mrg   /* Insert new NODE that has already filled key and value.  */
    253  1.3  mrg   fibonacci_node_t *insert_node (fibonacci_node_t *node);
    254  1.3  mrg 
    255  1.1  mrg   /* Insert it into the root list.  */
    256  1.1  mrg   void insert_root (fibonacci_node_t *node);
    257  1.1  mrg 
    258  1.1  mrg   /* Remove NODE from PARENT's child list.  */
    259  1.1  mrg   void cut (fibonacci_node_t *node, fibonacci_node_t *parent);
    260  1.1  mrg 
    261  1.1  mrg   /* Process cut of node Y and do it recursivelly.  */
    262  1.1  mrg   void cascading_cut (fibonacci_node_t *y);
    263  1.1  mrg 
    264  1.1  mrg   /* Extract minimum node from the heap.  */
    265  1.1  mrg   fibonacci_node_t * extract_minimum_node ();
    266  1.1  mrg 
    267  1.1  mrg   /* Remove root NODE from the heap.  */
    268  1.1  mrg   void remove_root (fibonacci_node_t *node);
    269  1.1  mrg 
    270  1.1  mrg   /* Consolidate heap.  */
    271  1.1  mrg   void consolidate ();
    272  1.1  mrg 
    273  1.1  mrg   /* Number of nodes.  */
    274  1.1  mrg   size_t m_nodes;
    275  1.1  mrg   /* Minimum node of the heap.  */
    276  1.1  mrg   fibonacci_node_t *m_min;
    277  1.1  mrg   /* Root node of the heap.  */
    278  1.1  mrg   fibonacci_node_t *m_root;
    279  1.1  mrg   /* Global minimum given in the heap construction.  */
    280  1.1  mrg   K m_global_min_key;
    281  1.6  mrg 
    282  1.6  mrg   /* Allocator used to hold nodes.  */
    283  1.6  mrg   pool_allocator *m_allocator;
    284  1.6  mrg   /* True if alocator is owned by the current heap only.  */
    285  1.6  mrg   bool m_own_allocator;
    286  1.1  mrg };
    287  1.1  mrg 
    288  1.1  mrg /* Remove fibonacci heap node.  */
    289  1.1  mrg 
    290  1.1  mrg template<class K, class V>
    291  1.1  mrg fibonacci_node<K,V> *
    292  1.1  mrg fibonacci_node<K,V>::remove ()
    293  1.1  mrg {
    294  1.1  mrg   fibonacci_node<K,V> *ret;
    295  1.1  mrg 
    296  1.1  mrg   if (this == m_left)
    297  1.1  mrg     ret = NULL;
    298  1.1  mrg   else
    299  1.1  mrg     ret = m_left;
    300  1.1  mrg 
    301  1.1  mrg   if (m_parent != NULL && m_parent->m_child == this)
    302  1.1  mrg     m_parent->m_child = ret;
    303  1.1  mrg 
    304  1.1  mrg   m_right->m_left = m_left;
    305  1.1  mrg   m_left->m_right = m_right;
    306  1.1  mrg 
    307  1.1  mrg   m_parent = NULL;
    308  1.1  mrg   m_left = this;
    309  1.1  mrg   m_right = this;
    310  1.1  mrg 
    311  1.1  mrg   return ret;
    312  1.1  mrg }
    313  1.1  mrg 
    314  1.1  mrg /* Link the node with PARENT.  */
    315  1.1  mrg 
    316  1.1  mrg template<class K, class V>
    317  1.1  mrg void
    318  1.1  mrg fibonacci_node<K,V>::link (fibonacci_node<K,V> *parent)
    319  1.1  mrg {
    320  1.1  mrg   if (parent->m_child == NULL)
    321  1.1  mrg     parent->m_child = this;
    322  1.1  mrg   else
    323  1.1  mrg     parent->m_child->insert_before (this);
    324  1.1  mrg   m_parent = parent;
    325  1.1  mrg   parent->m_degree++;
    326  1.1  mrg   m_mark = 0;
    327  1.1  mrg }
    328  1.1  mrg 
    329  1.1  mrg /* Put node B after this node.  */
    330  1.1  mrg 
    331  1.1  mrg template<class K, class V>
    332  1.1  mrg void
    333  1.1  mrg fibonacci_node<K,V>::insert_after (fibonacci_node<K,V> *b)
    334  1.1  mrg {
    335  1.1  mrg   fibonacci_node<K,V> *a = this;
    336  1.1  mrg 
    337  1.1  mrg   if (a == a->m_right)
    338  1.1  mrg     {
    339  1.1  mrg       a->m_right = b;
    340  1.1  mrg       a->m_left = b;
    341  1.1  mrg       b->m_right = a;
    342  1.1  mrg       b->m_left = a;
    343  1.1  mrg     }
    344  1.1  mrg   else
    345  1.1  mrg     {
    346  1.1  mrg       b->m_right = a->m_right;
    347  1.1  mrg       a->m_right->m_left = b;
    348  1.1  mrg       a->m_right = b;
    349  1.1  mrg       b->m_left = a;
    350  1.1  mrg     }
    351  1.1  mrg }
    352  1.1  mrg 
    353  1.1  mrg /* Insert new node given by KEY and DATA associated with the key.  */
    354  1.1  mrg 
    355  1.1  mrg template<class K, class V>
    356  1.1  mrg fibonacci_node<K,V>*
    357  1.1  mrg fibonacci_heap<K,V>::insert (K key, V *data)
    358  1.1  mrg {
    359  1.1  mrg   /* Create the new node.  */
    360  1.6  mrg   fibonacci_node<K,V> *node = new (m_allocator->allocate ())
    361  1.6  mrg 				  fibonacci_node_t (key, data);
    362  1.1  mrg 
    363  1.3  mrg   return insert_node (node);
    364  1.1  mrg }
    365  1.1  mrg 
    366  1.3  mrg /* Insert new NODE given by DATA associated with the key.  */
    367  1.1  mrg 
    368  1.1  mrg template<class K, class V>
    369  1.1  mrg fibonacci_node<K,V>*
    370  1.1  mrg fibonacci_heap<K,V>::insert (fibonacci_node_t *node, K key, V *data)
    371  1.1  mrg {
    372  1.1  mrg   /* Set the node's data.  */
    373  1.1  mrg   node->m_data = data;
    374  1.1  mrg   node->m_key = key;
    375  1.1  mrg 
    376  1.3  mrg   return insert_node (node);
    377  1.3  mrg }
    378  1.3  mrg 
    379  1.3  mrg /* Insert new NODE that has already filled key and value.  */
    380  1.3  mrg 
    381  1.3  mrg template<class K, class V>
    382  1.3  mrg fibonacci_node<K,V>*
    383  1.3  mrg fibonacci_heap<K,V>::insert_node (fibonacci_node_t *node)
    384  1.3  mrg {
    385  1.1  mrg   /* Insert it into the root list.  */
    386  1.1  mrg   insert_root (node);
    387  1.1  mrg 
    388  1.1  mrg   /* If their was no minimum, or this key is less than the min,
    389  1.1  mrg      it's the new min.  */
    390  1.1  mrg   if (m_min == NULL || node->m_key < m_min->m_key)
    391  1.1  mrg     m_min = node;
    392  1.1  mrg 
    393  1.1  mrg   m_nodes++;
    394  1.1  mrg 
    395  1.1  mrg   return node;
    396  1.1  mrg }
    397  1.1  mrg 
    398  1.1  mrg /* For given NODE, set new KEY and DATA value.  */
    399  1.3  mrg 
    400  1.1  mrg template<class K, class V>
    401  1.1  mrg V*
    402  1.1  mrg fibonacci_heap<K,V>::replace_key_data (fibonacci_node<K,V> *node, K key,
    403  1.1  mrg 				       V *data)
    404  1.1  mrg {
    405  1.1  mrg   K okey;
    406  1.1  mrg   fibonacci_node<K,V> *y;
    407  1.1  mrg   V *odata = node->m_data;
    408  1.1  mrg 
    409  1.1  mrg   /* If we wanted to, we do a real increase by redeleting and
    410  1.1  mrg      inserting.  */
    411  1.1  mrg   if (node->compare_data (key) > 0)
    412  1.1  mrg     {
    413  1.1  mrg       delete_node (node, false);
    414  1.1  mrg 
    415  1.1  mrg       node = new (node) fibonacci_node_t ();
    416  1.1  mrg       insert (node, key, data);
    417  1.1  mrg 
    418  1.1  mrg       return odata;
    419  1.1  mrg     }
    420  1.1  mrg 
    421  1.1  mrg   okey = node->m_key;
    422  1.1  mrg   node->m_data = data;
    423  1.1  mrg   node->m_key = key;
    424  1.1  mrg   y = node->m_parent;
    425  1.1  mrg 
    426  1.1  mrg   /* Short-circuit if the key is the same, as we then don't have to
    427  1.1  mrg      do anything.  Except if we're trying to force the new node to
    428  1.1  mrg      be the new minimum for delete.  */
    429  1.1  mrg   if (okey == key && okey != m_global_min_key)
    430  1.1  mrg     return odata;
    431  1.1  mrg 
    432  1.1  mrg   /* These two compares are specifically <= 0 to make sure that in the case
    433  1.1  mrg      of equality, a node we replaced the data on, becomes the new min.  This
    434  1.1  mrg      is needed so that delete's call to extractmin gets the right node.  */
    435  1.1  mrg   if (y != NULL && node->compare (y) <= 0)
    436  1.1  mrg     {
    437  1.1  mrg       cut (node, y);
    438  1.1  mrg       cascading_cut (y);
    439  1.1  mrg     }
    440  1.1  mrg 
    441  1.1  mrg   if (node->compare (m_min) <= 0)
    442  1.1  mrg     m_min = node;
    443  1.1  mrg 
    444  1.1  mrg   return odata;
    445  1.1  mrg }
    446  1.1  mrg 
    447  1.3  mrg /* Extract minimum node in the heap.  Delete fibonacci node if RELEASE
    448  1.3  mrg    is true.  */
    449  1.3  mrg 
    450  1.1  mrg template<class K, class V>
    451  1.1  mrg V*
    452  1.1  mrg fibonacci_heap<K,V>::extract_min (bool release)
    453  1.1  mrg {
    454  1.1  mrg   fibonacci_node<K,V> *z;
    455  1.1  mrg   V *ret = NULL;
    456  1.1  mrg 
    457  1.1  mrg   /* If we don't have a min set, it means we have no nodes.  */
    458  1.1  mrg   if (m_min != NULL)
    459  1.1  mrg     {
    460  1.1  mrg       /* Otherwise, extract the min node, free the node, and return the
    461  1.1  mrg        node's data.  */
    462  1.1  mrg       z = extract_minimum_node ();
    463  1.1  mrg       ret = z->m_data;
    464  1.1  mrg 
    465  1.1  mrg       if (release)
    466  1.6  mrg 	{
    467  1.6  mrg 	  z->~fibonacci_node_t ();
    468  1.6  mrg 	  m_allocator->remove (z);
    469  1.6  mrg 	}
    470  1.1  mrg     }
    471  1.1  mrg 
    472  1.1  mrg   return ret;
    473  1.1  mrg }
    474  1.1  mrg 
    475  1.1  mrg /* Delete NODE in the heap, if RELEASE is specified memory is released.  */
    476  1.1  mrg 
    477  1.1  mrg template<class K, class V>
    478  1.1  mrg V*
    479  1.1  mrg fibonacci_heap<K,V>::delete_node (fibonacci_node<K,V> *node, bool release)
    480  1.1  mrg {
    481  1.1  mrg   V *ret = node->m_data;
    482  1.1  mrg 
    483  1.1  mrg   /* To perform delete, we just make it the min key, and extract.  */
    484  1.1  mrg   replace_key (node, m_global_min_key);
    485  1.1  mrg   if (node != m_min)
    486  1.1  mrg     {
    487  1.1  mrg       fprintf (stderr, "Can't force minimum on fibheap.\n");
    488  1.1  mrg       abort ();
    489  1.1  mrg     }
    490  1.1  mrg   extract_min (release);
    491  1.1  mrg 
    492  1.1  mrg   return ret;
    493  1.1  mrg }
    494  1.1  mrg 
    495  1.3  mrg /* Union the heap with HEAPB.  One of the heaps is going to be deleted.  */
    496  1.1  mrg 
    497  1.1  mrg template<class K, class V>
    498  1.1  mrg fibonacci_heap<K,V>*
    499  1.1  mrg fibonacci_heap<K,V>::union_with (fibonacci_heap<K,V> *heapb)
    500  1.1  mrg {
    501  1.1  mrg   fibonacci_heap<K,V> *heapa = this;
    502  1.1  mrg 
    503  1.3  mrg   fibonacci_node<K,V> *a_root, *b_root;
    504  1.1  mrg 
    505  1.6  mrg   /* Both heaps must share allocator.  */
    506  1.6  mrg   gcc_checking_assert (m_allocator == heapb->m_allocator);
    507  1.6  mrg 
    508  1.1  mrg   /* If one of the heaps is empty, the union is just the other heap.  */
    509  1.1  mrg   if ((a_root = heapa->m_root) == NULL)
    510  1.1  mrg     {
    511  1.1  mrg       delete (heapa);
    512  1.1  mrg       return heapb;
    513  1.1  mrg     }
    514  1.1  mrg   if ((b_root = heapb->m_root) == NULL)
    515  1.1  mrg     {
    516  1.1  mrg       delete (heapb);
    517  1.1  mrg       return heapa;
    518  1.1  mrg     }
    519  1.1  mrg 
    520  1.1  mrg   /* Merge them to the next nodes on the opposite chain.  */
    521  1.1  mrg   a_root->m_left->m_right = b_root;
    522  1.1  mrg   b_root->m_left->m_right = a_root;
    523  1.3  mrg   std::swap (a_root->m_left, b_root->m_left);
    524  1.1  mrg   heapa->m_nodes += heapb->m_nodes;
    525  1.1  mrg 
    526  1.1  mrg   /* And set the new minimum, if it's changed.  */
    527  1.3  mrg   if (heapb->m_min->compare (heapa->m_min) < 0)
    528  1.1  mrg     heapa->m_min = heapb->m_min;
    529  1.1  mrg 
    530  1.3  mrg   /* Set m_min to NULL to not to delete live fibonacci nodes.  */
    531  1.3  mrg   heapb->m_min = NULL;
    532  1.1  mrg   delete (heapb);
    533  1.3  mrg 
    534  1.1  mrg   return heapa;
    535  1.1  mrg }
    536  1.1  mrg 
    537  1.1  mrg /* Insert it into the root list.  */
    538  1.1  mrg 
    539  1.1  mrg template<class K, class V>
    540  1.1  mrg void
    541  1.1  mrg fibonacci_heap<K,V>::insert_root (fibonacci_node_t *node)
    542  1.1  mrg {
    543  1.1  mrg   /* If the heap is currently empty, the new node becomes the singleton
    544  1.1  mrg      circular root list.  */
    545  1.1  mrg   if (m_root == NULL)
    546  1.1  mrg     {
    547  1.1  mrg       m_root = node;
    548  1.1  mrg       node->m_left = node;
    549  1.1  mrg       node->m_right = node;
    550  1.1  mrg       return;
    551  1.1  mrg     }
    552  1.1  mrg 
    553  1.1  mrg   /* Otherwise, insert it in the circular root list between the root
    554  1.1  mrg      and it's right node.  */
    555  1.1  mrg   m_root->insert_after (node);
    556  1.1  mrg }
    557  1.1  mrg 
    558  1.1  mrg /* Remove NODE from PARENT's child list.  */
    559  1.1  mrg 
    560  1.1  mrg template<class K, class V>
    561  1.1  mrg void
    562  1.1  mrg fibonacci_heap<K,V>::cut (fibonacci_node<K,V> *node,
    563  1.1  mrg 			  fibonacci_node<K,V> *parent)
    564  1.1  mrg {
    565  1.1  mrg   node->remove ();
    566  1.1  mrg   parent->m_degree--;
    567  1.1  mrg   insert_root (node);
    568  1.1  mrg   node->m_parent = NULL;
    569  1.1  mrg   node->m_mark = 0;
    570  1.1  mrg }
    571  1.1  mrg 
    572  1.1  mrg /* Process cut of node Y and do it recursivelly.  */
    573  1.1  mrg 
    574  1.1  mrg template<class K, class V>
    575  1.1  mrg void
    576  1.1  mrg fibonacci_heap<K,V>::cascading_cut (fibonacci_node<K,V> *y)
    577  1.1  mrg {
    578  1.1  mrg   fibonacci_node<K,V> *z;
    579  1.1  mrg 
    580  1.1  mrg   while ((z = y->m_parent) != NULL)
    581  1.1  mrg     {
    582  1.1  mrg       if (y->m_mark == 0)
    583  1.1  mrg 	{
    584  1.1  mrg 	  y->m_mark = 1;
    585  1.1  mrg 	  return;
    586  1.1  mrg 	}
    587  1.1  mrg       else
    588  1.1  mrg 	{
    589  1.1  mrg 	  cut (y, z);
    590  1.1  mrg 	  y = z;
    591  1.1  mrg 	}
    592  1.1  mrg     }
    593  1.1  mrg }
    594  1.1  mrg 
    595  1.1  mrg /* Extract minimum node from the heap.  */
    596  1.3  mrg 
    597  1.1  mrg template<class K, class V>
    598  1.1  mrg fibonacci_node<K,V>*
    599  1.1  mrg fibonacci_heap<K,V>::extract_minimum_node ()
    600  1.1  mrg {
    601  1.1  mrg   fibonacci_node<K,V> *ret = m_min;
    602  1.1  mrg   fibonacci_node<K,V> *x, *y, *orig;
    603  1.1  mrg 
    604  1.1  mrg   /* Attach the child list of the minimum node to the root list of the heap.
    605  1.1  mrg      If there is no child list, we don't do squat.  */
    606  1.1  mrg   for (x = ret->m_child, orig = NULL; x != orig && x != NULL; x = y)
    607  1.1  mrg     {
    608  1.1  mrg       if (orig == NULL)
    609  1.1  mrg 	orig = x;
    610  1.1  mrg       y = x->m_right;
    611  1.1  mrg       x->m_parent = NULL;
    612  1.1  mrg       insert_root (x);
    613  1.1  mrg     }
    614  1.1  mrg 
    615  1.1  mrg   /* Remove the old root.  */
    616  1.1  mrg   remove_root (ret);
    617  1.1  mrg   m_nodes--;
    618  1.1  mrg 
    619  1.1  mrg   /* If we are left with no nodes, then the min is NULL.  */
    620  1.1  mrg   if (m_nodes == 0)
    621  1.1  mrg     m_min = NULL;
    622  1.1  mrg   else
    623  1.1  mrg     {
    624  1.1  mrg       /* Otherwise, consolidate to find new minimum, as well as do the reorg
    625  1.1  mrg        work that needs to be done.  */
    626  1.1  mrg       m_min = ret->m_right;
    627  1.1  mrg       consolidate ();
    628  1.1  mrg     }
    629  1.1  mrg 
    630  1.1  mrg   return ret;
    631  1.1  mrg }
    632  1.1  mrg 
    633  1.1  mrg /* Remove root NODE from the heap.  */
    634  1.1  mrg 
    635  1.1  mrg template<class K, class V>
    636  1.1  mrg void
    637  1.1  mrg fibonacci_heap<K,V>::remove_root (fibonacci_node<K,V> *node)
    638  1.1  mrg {
    639  1.1  mrg   if (node->m_left == node)
    640  1.1  mrg     m_root = NULL;
    641  1.1  mrg   else
    642  1.1  mrg     m_root = node->remove ();
    643  1.1  mrg }
    644  1.1  mrg 
    645  1.1  mrg /* Consolidate heap.  */
    646  1.1  mrg 
    647  1.1  mrg template<class K, class V>
    648  1.1  mrg void fibonacci_heap<K,V>::consolidate ()
    649  1.1  mrg {
    650  1.6  mrg   const int D = 1 + 8 * sizeof (long);
    651  1.6  mrg   fibonacci_node<K,V> *a[D];
    652  1.1  mrg   fibonacci_node<K,V> *w, *x, *y;
    653  1.1  mrg   int i, d;
    654  1.1  mrg 
    655  1.6  mrg   memset (a, 0, sizeof (a));
    656  1.6  mrg 
    657  1.1  mrg   while ((w = m_root) != NULL)
    658  1.1  mrg     {
    659  1.1  mrg       x = w;
    660  1.1  mrg       remove_root (w);
    661  1.1  mrg       d = x->m_degree;
    662  1.6  mrg       gcc_checking_assert (d < D);
    663  1.1  mrg       while (a[d] != NULL)
    664  1.1  mrg 	{
    665  1.1  mrg 	  y = a[d];
    666  1.1  mrg 	  if (x->compare (y) > 0)
    667  1.1  mrg 	    std::swap (x, y);
    668  1.1  mrg 	  y->link (x);
    669  1.1  mrg 	  a[d] = NULL;
    670  1.1  mrg 	  d++;
    671  1.1  mrg 	}
    672  1.1  mrg       a[d] = x;
    673  1.1  mrg     }
    674  1.1  mrg   m_min = NULL;
    675  1.1  mrg   for (i = 0; i < D; i++)
    676  1.1  mrg     if (a[i] != NULL)
    677  1.1  mrg       {
    678  1.1  mrg 	insert_root (a[i]);
    679  1.1  mrg 	if (m_min == NULL || a[i]->compare (m_min) < 0)
    680  1.1  mrg 	  m_min = a[i];
    681  1.1  mrg       }
    682  1.1  mrg }
    683  1.1  mrg 
    684  1.1  mrg #endif  // GCC_FIBONACCI_HEAP_H
    685