source: trunk/binutils/libiberty/fibheap.c@ 3022

Last change on this file since 3022 was 607, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 11.0 KB
Line 
1/* A Fibonacci heap datatype.
2 Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3 Contributed by Daniel Berlin (dan@cgsoftware.com).
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25#ifdef HAVE_LIMITS_H
26#include <limits.h>
27#endif
28#ifdef HAVE_STDLIB_H
29#include <stdlib.h>
30#endif
31#ifdef HAVE_STRING_H
32#include <string.h>
33#endif
34#include "libiberty.h"
35#include "fibheap.h"
36
37
38#define FIBHEAPKEY_MIN LONG_MIN
39
40static void fibheap_ins_root PARAMS ((fibheap_t, fibnode_t));
41static void fibheap_rem_root PARAMS ((fibheap_t, fibnode_t));
42static void fibheap_consolidate PARAMS ((fibheap_t));
43static void fibheap_link PARAMS ((fibheap_t, fibnode_t, fibnode_t));
44static void fibheap_cut PARAMS ((fibheap_t, fibnode_t, fibnode_t));
45static void fibheap_cascading_cut PARAMS ((fibheap_t, fibnode_t));
46static fibnode_t fibheap_extr_min_node PARAMS ((fibheap_t));
47static int fibheap_compare PARAMS ((fibheap_t, fibnode_t, fibnode_t));
48static int fibheap_comp_data PARAMS ((fibheap_t, fibheapkey_t, void *,
49 fibnode_t));
50static fibnode_t fibnode_new PARAMS ((void));
51static void fibnode_insert_after PARAMS ((fibnode_t, fibnode_t));
52#define fibnode_insert_before(a, b) fibnode_insert_after (a->left, b)
53static fibnode_t fibnode_remove PARAMS ((fibnode_t));
54
55
56
57/* Create a new fibonacci heap. */
58fibheap_t
59fibheap_new ()
60{
61 return (fibheap_t) xcalloc (1, sizeof (struct fibheap));
62}
63
64/* Create a new fibonacci heap node. */
65static fibnode_t
66fibnode_new ()
67{
68 fibnode_t node;
69
70 node = (fibnode_t) xcalloc (1, sizeof *node);
71 node->left = node;
72 node->right = node;
73
74 return node;
75}
76
77static inline int
78fibheap_compare (heap, a, b)
79 fibheap_t heap ATTRIBUTE_UNUSED;
80 fibnode_t a;
81 fibnode_t b;
82{
83 if (a->key < b->key)
84 return -1;
85 if (a->key > b->key)
86 return 1;
87 return 0;
88}
89
90static inline int
91fibheap_comp_data (heap, key, data, b)
92 fibheap_t heap;
93 fibheapkey_t key;
94 void *data;
95 fibnode_t b;
96{
97 struct fibnode a;
98
99 a.key = key;
100 a.data = data;
101
102 return fibheap_compare (heap, &a, b);
103}
104
105/* Insert DATA, with priority KEY, into HEAP. */
106fibnode_t
107fibheap_insert (heap, key, data)
108 fibheap_t heap;
109 fibheapkey_t key;
110 void *data;
111{
112 fibnode_t node;
113
114 /* Create the new node. */
115 node = fibnode_new ();
116
117 /* Set the node's data. */
118 node->data = data;
119 node->key = key;
120
121 /* Insert it into the root list. */
122 fibheap_ins_root (heap, node);
123
124 /* If their was no minimum, or this key is less than the min,
125 it's the new min. */
126 if (heap->min == NULL || node->key < heap->min->key)
127 heap->min = node;
128
129 heap->nodes++;
130
131 return node;
132}
133
134/* Return the data of the minimum node (if we know it). */
135void *
136fibheap_min (heap)
137 fibheap_t heap;
138{
139 /* If there is no min, we can't easily return it. */
140 if (heap->min == NULL)
141 return NULL;
142 return heap->min->data;
143}
144
145/* Return the key of the minimum node (if we know it). */
146fibheapkey_t
147fibheap_min_key (heap)
148 fibheap_t heap;
149{
150 /* If there is no min, we can't easily return it. */
151 if (heap->min == NULL)
152 return 0;
153 return heap->min->key;
154}
155
156/* Union HEAPA and HEAPB into a new heap. */
157fibheap_t
158fibheap_union (heapa, heapb)
159 fibheap_t heapa;
160 fibheap_t heapb;
161{
162 fibnode_t a_root, b_root, temp;
163
164 /* If one of the heaps is empty, the union is just the other heap. */
165 if ((a_root = heapa->root) == NULL)
166 {
167 free (heapa);
168 return heapb;
169 }
170 if ((b_root = heapb->root) == NULL)
171 {
172 free (heapb);
173 return heapa;
174 }
175
176 /* Merge them to the next nodes on the opposite chain. */
177 a_root->left->right = b_root;
178 b_root->left->right = a_root;
179 temp = a_root->left;
180 a_root->left = b_root->left;
181 b_root->left = temp;
182 heapa->nodes += heapb->nodes;
183
184 /* And set the new minimum, if it's changed. */
185 if (fibheap_compare (heapa, heapb->min, heapa->min) < 0)
186 heapa->min = heapb->min;
187
188 free (heapb);
189 return heapa;
190}
191
192/* Extract the data of the minimum node from HEAP. */
193void *
194fibheap_extract_min (heap)
195 fibheap_t heap;
196{
197 fibnode_t z;
198 void *ret = NULL;
199
200 /* If we don't have a min set, it means we have no nodes. */
201 if (heap->min != NULL)
202 {
203 /* Otherwise, extract the min node, free the node, and return the
204 node's data. */
205 z = fibheap_extr_min_node (heap);
206 ret = z->data;
207 free (z);
208 }
209
210 return ret;
211}
212
213/* Replace both the KEY and the DATA associated with NODE. */
214void *
215fibheap_replace_key_data (heap, node, key, data)
216 fibheap_t heap;
217 fibnode_t node;
218 fibheapkey_t key;
219 void *data;
220{
221 void *odata;
222 int okey;
223 fibnode_t y;
224
225 /* If we wanted to, we could actually do a real increase by redeleting and
226 inserting. However, this would require O (log n) time. So just bail out
227 for now. */
228 if (fibheap_comp_data (heap, key, data, node) > 0)
229 return NULL;
230
231 odata = node->data;
232 okey = node->key;
233 node->data = data;
234 node->key = key;
235 y = node->parent;
236
237 if (okey == key)
238 return odata;
239
240 /* These two compares are specifically <= 0 to make sure that in the case
241 of equality, a node we replaced the data on, becomes the new min. This
242 is needed so that delete's call to extractmin gets the right node. */
243 if (y != NULL && fibheap_compare (heap, node, y) <= 0)
244 {
245 fibheap_cut (heap, node, y);
246 fibheap_cascading_cut (heap, y);
247 }
248
249 if (fibheap_compare (heap, node, heap->min) <= 0)
250 heap->min = node;
251
252 return odata;
253}
254
255/* Replace the DATA associated with NODE. */
256void *
257fibheap_replace_data (heap, node, data)
258 fibheap_t heap;
259 fibnode_t node;
260 void *data;
261{
262 return fibheap_replace_key_data (heap, node, node->key, data);
263}
264
265/* Replace the KEY associated with NODE. */
266fibheapkey_t
267fibheap_replace_key (heap, node, key)
268 fibheap_t heap;
269 fibnode_t node;
270 fibheapkey_t key;
271{
272 int okey = node->key;
273 fibheap_replace_key_data (heap, node, key, node->data);
274 return okey;
275}
276
277/* Delete NODE from HEAP. */
278void *
279fibheap_delete_node (heap, node)
280 fibheap_t heap;
281 fibnode_t node;
282{
283 void *ret = node->data;
284
285 /* To perform delete, we just make it the min key, and extract. */
286 fibheap_replace_key (heap, node, FIBHEAPKEY_MIN);
287 fibheap_extract_min (heap);
288
289 return ret;
290}
291
292/* Delete HEAP. */
293void
294fibheap_delete (heap)
295 fibheap_t heap;
296{
297 while (heap->min != NULL)
298 free (fibheap_extr_min_node (heap));
299
300 free (heap);
301}
302
303/* Determine if HEAP is empty. */
304int
305fibheap_empty (heap)
306 fibheap_t heap;
307{
308 return heap->nodes == 0;
309}
310
311/* Extract the minimum node of the heap. */
312static fibnode_t
313fibheap_extr_min_node (heap)
314 fibheap_t heap;
315{
316 fibnode_t ret = heap->min;
317 fibnode_t x, y, orig;
318
319 /* Attach the child list of the minimum node to the root list of the heap.
320 If there is no child list, we don't do squat. */
321 for (x = ret->child, orig = NULL; x != orig && x != NULL; x = y)
322 {
323 if (orig == NULL)
324 orig = x;
325 y = x->right;
326 x->parent = NULL;
327 fibheap_ins_root (heap, x);
328 }
329
330 /* Remove the old root. */
331 fibheap_rem_root (heap, ret);
332 heap->nodes--;
333
334 /* If we are left with no nodes, then the min is NULL. */
335 if (heap->nodes == 0)
336 heap->min = NULL;
337 else
338 {
339 /* Otherwise, consolidate to find new minimum, as well as do the reorg
340 work that needs to be done. */
341 heap->min = ret->right;
342 fibheap_consolidate (heap);
343 }
344
345 return ret;
346}
347
348/* Insert NODE into the root list of HEAP. */
349static void
350fibheap_ins_root (heap, node)
351 fibheap_t heap;
352 fibnode_t node;
353{
354 /* If the heap is currently empty, the new node becomes the singleton
355 circular root list. */
356 if (heap->root == NULL)
357 {
358 heap->root = node;
359 node->left = node;
360 node->right = node;
361 return;
362 }
363
364 /* Otherwise, insert it in the circular root list between the root
365 and it's right node. */
366 fibnode_insert_after (heap->root, node);
367}
368
369/* Remove NODE from the rootlist of HEAP. */
370static void
371fibheap_rem_root (heap, node)
372 fibheap_t heap;
373 fibnode_t node;
374{
375 if (node->left == node)
376 heap->root = NULL;
377 else
378 heap->root = fibnode_remove (node);
379}
380
381/* Consolidate the heap. */
382static void
383fibheap_consolidate (heap)
384 fibheap_t heap;
385{
386 fibnode_t a[1 + 8 * sizeof (long)];
387 fibnode_t w;
388 fibnode_t y;
389 fibnode_t x;
390 int i;
391 int d;
392 int D;
393
394 D = 1 + 8 * sizeof (long);
395
396 memset (a, 0, sizeof (fibnode_t) * D);
397
398 while ((w = heap->root) != NULL)
399 {
400 x = w;
401 fibheap_rem_root (heap, w);
402 d = x->degree;
403 while (a[d] != NULL)
404 {
405 y = a[d];
406 if (fibheap_compare (heap, x, y) > 0)
407 {
408 fibnode_t temp;
409 temp = x;
410 x = y;
411 y = temp;
412 }
413 fibheap_link (heap, y, x);
414 a[d] = NULL;
415 d++;
416 }
417 a[d] = x;
418 }
419 heap->min = NULL;
420 for (i = 0; i < D; i++)
421 if (a[i] != NULL)
422 {
423 fibheap_ins_root (heap, a[i]);
424 if (heap->min == NULL || fibheap_compare (heap, a[i], heap->min) < 0)
425 heap->min = a[i];
426 }
427}
428
429/* Make NODE a child of PARENT. */
430static void
431fibheap_link (heap, node, parent)
432 fibheap_t heap ATTRIBUTE_UNUSED;
433 fibnode_t node;
434 fibnode_t parent;
435{
436 if (parent->child == NULL)
437 parent->child = node;
438 else
439 fibnode_insert_before (parent->child, node);
440 node->parent = parent;
441 parent->degree++;
442 node->mark = 0;
443}
444
445/* Remove NODE from PARENT's child list. */
446static void
447fibheap_cut (heap, node, parent)
448 fibheap_t heap;
449 fibnode_t node;
450 fibnode_t parent;
451{
452 fibnode_remove (node);
453 parent->degree--;
454 fibheap_ins_root (heap, node);
455 node->parent = NULL;
456 node->mark = 0;
457}
458
459static void
460fibheap_cascading_cut (heap, y)
461 fibheap_t heap;
462 fibnode_t y;
463{
464 fibnode_t z;
465
466 while ((z = y->parent) != NULL)
467 {
468 if (y->mark == 0)
469 {
470 y->mark = 1;
471 return;
472 }
473 else
474 {
475 fibheap_cut (heap, y, z);
476 y = z;
477 }
478 }
479}
480
481static void
482fibnode_insert_after (a, b)
483 fibnode_t a;
484 fibnode_t b;
485{
486 if (a == a->right)
487 {
488 a->right = b;
489 a->left = b;
490 b->right = a;
491 b->left = a;
492 }
493 else
494 {
495 b->right = a->right;
496 a->right->left = b;
497 a->right = b;
498 b->left = a;
499 }
500}
501
502static fibnode_t
503fibnode_remove (node)
504 fibnode_t node;
505{
506 fibnode_t ret;
507
508 if (node == node->left)
509 ret = NULL;
510 else
511 ret = node->left;
512
513 if (node->parent != NULL && node->parent->child == node)
514 node->parent->child = ret;
515
516 node->right->left = node->left;
517 node->left->right = node->right;
518
519 node->parent = NULL;
520 node->left = node;
521 node->right = node;
522
523 return ret;
524}
Note: See TracBrowser for help on using the repository browser.