source: branches/libc-0.6/src/gcc/libiberty/fibheap.c

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • 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.