1 1.3 mrg /* Fibonacci heap for GNU compiler. 2 1.7 mrg Copyright (C) 1998-2022 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