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