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