4 * This file is part of SOAPdenovo.
9 * Copyright 1997-2003 John-Mark Gurney.
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * $Id: fib.c,v 1.10 2007/10/19 13:09:26 zerbino Exp $
42 #define HEAPBLOCKSIZE 10000
44 static int fh_comparedata ( FibHeap
* h
, Coordinate key
, unsigned int data
, FibHeapNode
* b
);
45 unsigned int fh_replacekeydata ( FibHeap
* h
, FibHeapNode
* x
, Coordinate key
, unsigned int data
);
47 static FibHeapNode
* allocateFibHeapEl ( FibHeap
* heap
)
49 return ( FibHeapNode
* ) getItem ( heap
->nodeMemory
);
52 static void deallocateFibHeapEl ( FibHeapNode
* a
, FibHeap
* heap
)
54 returnItem ( heap
->nodeMemory
, a
);
57 #define swap(type, a, b) \
65 #define INT_BITS (sizeof(IDnum) * 8)
67 static inline IDnum
ceillog2 ( IDnum a
)
80 cons
= ( ( IDnum
) 1 ) << b
;
95 if ( ( ( ( IDnum
) 1 << i
) ) == oa
)
106 * Private Heap Functions
108 static void fh_initheap ( FibHeap
* new )
110 new->fh_cmp_fnct
= NULL
;
111 new->nodeMemory
= createMem_manager ( sizeof ( FibHeapNode
), HEAPBLOCKSIZE
);
121 static void fh_destroyheap ( FibHeap
* h
)
123 h
->fh_cmp_fnct
= NULL
;
126 if ( h
->fh_cons
!= NULL
)
136 * Public Heap Functions
138 FibHeap
* fh_makekeyheap ()
142 if ( ( n
= malloc ( sizeof * n
) ) == NULL
)
152 FibHeap
* fh_makeheap ()
156 if ( ( n
= malloc ( sizeof * n
) ) == NULL
)
165 voidcmp
fh_setcmp ( FibHeap
* h
, voidcmp fnct
)
168 oldfnct
= h
->fh_cmp_fnct
;
169 h
->fh_cmp_fnct
= fnct
;
173 unsigned int fh_setneginf ( FibHeap
* h
, unsigned int data
)
181 FibHeap
* fh_union ( FibHeap
* ha
, FibHeap
* hb
)
185 if ( ha
->fh_root
== NULL
|| hb
->fh_root
== NULL
)
187 /* either one or both are empty */
188 if ( ha
->fh_root
== NULL
)
190 fh_destroyheap ( ha
);
195 fh_destroyheap ( hb
);
200 ha
->fh_root
->fhe_left
->fhe_right
= hb
->fh_root
;
201 hb
->fh_root
->fhe_left
->fhe_right
= ha
->fh_root
;
202 x
= ha
->fh_root
->fhe_left
;
203 ha
->fh_root
->fhe_left
= hb
->fh_root
->fhe_left
;
204 hb
->fh_root
->fhe_left
= x
;
205 ha
->fh_n
+= hb
->fh_n
;
207 * we probably should also keep stats on number of unions
210 /* set fh_min if necessary */
211 if ( fh_compare ( ha
, hb
->fh_min
, ha
->fh_min
) < 0 )
213 ha
->fh_min
= hb
->fh_min
;
216 fh_destroyheap ( hb
);
220 void fh_deleteheap ( FibHeap
* h
)
222 freeMem_manager ( h
->nodeMemory
);
223 h
->nodeMemory
= NULL
;
224 fh_destroyheap ( h
);
228 * Public Key Heap Functions
230 FibHeapNode
* fh_insertkey ( FibHeap
* h
, Coordinate key
, unsigned int data
)
234 if ( ( x
= fhe_newelem ( h
) ) == NULL
)
239 /* just insert on root list, and make sure it's not the new min */
242 fh_insertel ( h
, x
);
246 boolean
fh_isempty ( FibHeap
* h
)
248 if ( h
->fh_min
== NULL
)
258 Coordinate
fh_minkey ( FibHeap
* h
)
260 if ( h
->fh_min
== NULL
)
265 return h
->fh_min
->fhe_key
;
268 unsigned int fh_replacekeydata ( FibHeap
* h
, FibHeapNode
* x
, Coordinate key
, unsigned int data
)
278 * we can increase a key by deleting and reinserting, that
279 * requires O(lgn) time.
281 if ( ( r
= fh_comparedata ( h
, key
, data
, x
) ) > 0 )
283 /* XXX - bad code! */
290 /* because they are equal, we don't have to do anything */
298 if ( h
->fh_keys
&& okey
== key
)
303 if ( y
!= NULL
&& fh_compare ( h
, x
, y
) <= 0 )
306 fh_cascading_cut ( h
, y
);
310 * the = is so that the call from fh_delete will delete the proper
313 if ( fh_compare ( h
, x
, h
->fh_min
) <= 0 )
321 Coordinate
fh_replacekey ( FibHeap
* h
, FibHeapNode
* x
, Coordinate key
)
325 ( void ) fh_replacekeydata ( h
, x
, key
, x
->fhe_data
);
330 * Public void * Heap Functions
333 * this will return these values:
334 * NULL failed for some reason
335 * ptr token to use for manipulation of data
337 FibHeapNode
* fh_insert ( FibHeap
* h
, unsigned int data
)
341 if ( ( x
= fhe_newelem ( h
) ) == NULL
)
346 /* just insert on root list, and make sure it's not the new min */
348 fh_insertel ( h
, x
);
352 unsigned int fh_min ( FibHeap
* h
)
354 if ( h
->fh_min
== NULL
)
359 return h
->fh_min
->fhe_data
;
362 unsigned int fh_extractmin ( FibHeap
* h
)
365 unsigned int ret
= 0;
367 if ( h
->fh_min
!= NULL
)
369 z
= fh_extractminel ( h
);
372 deallocateFibHeapEl ( z
, h
);
379 unsigned int fh_replacedata ( FibHeapNode
* x
, unsigned int data
)
381 unsigned int odata
= x
->fhe_data
;
386 unsigned int fh_delete ( FibHeap
* h
, FibHeapNode
* x
)
393 fh_replacedata ( x
, h
->fh_neginf
);
397 fh_replacekey ( h
, x
, INT_MIN
);
405 * begin of private element fuctions
407 static FibHeapNode
* fh_extractminel ( FibHeap
* h
)
410 FibHeapNode
* x
, *y
, *orig
;
414 /* put all the children on the root list */
415 /* for true consistancy, we should use fhe_remove */
416 for ( x
= ret
->fhe_child
; x
!= orig
&& x
!= NULL
; )
425 fh_insertrootlist ( h
, x
);
429 /* remove minimum from root list */
430 fh_removerootlist ( h
, ret
);
433 /* if we aren't empty, consolidate the heap */
440 h
->fh_min
= ret
->fhe_right
;
441 fh_consolidate ( h
);
447 static void fh_insertrootlist ( FibHeap
* h
, FibHeapNode
* x
)
449 if ( h
->fh_root
== NULL
)
457 fhe_insertafter ( h
->fh_root
, x
);
460 static void fh_removerootlist ( FibHeap
* h
, FibHeapNode
* x
)
462 if ( x
->fhe_left
== x
)
468 h
->fh_root
= fhe_remove ( x
);
472 static void fh_consolidate ( FibHeap
* h
)
482 /* assign a the value of h->fh_cons so I don't have to rewrite code */
486 for ( i
= 0; i
< D
; i
++ )
491 while ( ( w
= h
->fh_root
) != NULL
)
494 fh_removerootlist ( h
, w
);
497 /* XXX - assert that d < D */
498 while ( a
[d
] != NULL
)
502 if ( fh_compare ( h
, x
, y
) > 0 )
504 swap ( FibHeapNode
*, x
, y
);
507 fh_heaplink ( h
, y
, x
);
517 for ( i
= 0; i
< D
; i
++ )
520 fh_insertrootlist ( h
, a
[i
] );
522 if ( h
->fh_min
== NULL
|| fh_compare ( h
, a
[i
], h
->fh_min
) < 0 )
529 static void fh_heaplink ( FibHeap
* h
, FibHeapNode
* y
, FibHeapNode
* x
)
531 /* make y a child of x */
532 if ( x
->fhe_child
== NULL
)
538 fhe_insertbefore ( x
->fhe_child
, y
);
546 static void fh_cut ( FibHeap
* h
, FibHeapNode
* x
, FibHeapNode
* y
)
550 fh_insertrootlist ( h
, x
);
555 static void fh_cascading_cut ( FibHeap
* h
, FibHeapNode
* y
)
559 while ( ( z
= y
->fhe_p
) != NULL
)
561 if ( y
->fhe_mark
== 0 )
575 * begining of handling elements of fibheap
577 static FibHeapNode
* fhe_newelem ( FibHeap
* h
)
581 if ( ( e
= allocateFibHeapEl ( h
) ) == NULL
)
590 static void fhe_initelem ( FibHeapNode
* e
)
601 static void fhe_insertafter ( FibHeapNode
* a
, FibHeapNode
* b
)
603 if ( a
== a
->fhe_right
)
612 b
->fhe_right
= a
->fhe_right
;
613 a
->fhe_right
->fhe_left
= b
;
619 static inline void fhe_insertbefore ( FibHeapNode
* a
, FibHeapNode
* b
)
621 fhe_insertafter ( a
->fhe_left
, b
);
624 static FibHeapNode
* fhe_remove ( FibHeapNode
* x
)
628 if ( x
== x
->fhe_left
)
637 /* fix the parent pointer */
638 if ( x
->fhe_p
!= NULL
&& x
->fhe_p
->fhe_child
== x
)
640 x
->fhe_p
->fhe_child
= ret
;
643 x
->fhe_right
->fhe_left
= x
->fhe_left
;
644 x
->fhe_left
->fhe_right
= x
->fhe_right
;
645 /* clear out hanging pointers */
652 static void fh_checkcons ( FibHeap
* h
)
656 /* make sure we have enough memory allocated to "reorganize" */
657 if ( h
->fh_Dl
== -1 || h
->fh_n
> ( 1 << h
->fh_Dl
) )
661 if ( ( h
->fh_Dl
= ceillog2 ( h
->fh_n
) + 1 ) < 8 )
666 if ( oDl
!= h
->fh_Dl
)
667 { h
->fh_cons
= ( FibHeapNode
** ) realloc ( h
->fh_cons
, sizeof * h
->fh_cons
* ( h
->fh_Dl
+ 1 ) ); }
669 if ( h
->fh_cons
== NULL
)
676 static int fh_compare ( FibHeap
* h
, FibHeapNode
* a
, FibHeapNode
* b
)
678 if ( a
->fhe_key
< b
->fhe_key
)
683 if ( a
->fhe_key
== b
->fhe_key
)
691 static int fh_comparedata ( FibHeap
* h
, Coordinate key
, unsigned int data
, FibHeapNode
* b
)
696 return fh_compare ( h
, &a
, b
);
699 static void fh_insertel ( FibHeap
* h
, FibHeapNode
* x
)
701 fh_insertrootlist ( h
, x
);
703 if ( h
->fh_min
== NULL
|| ( h
->fh_keys
? x
->fhe_key
< h
->fh_min
->fhe_key
: h
->fh_cmp_fnct ( x
->fhe_data
, h
->fh_min
->fhe_data
) < 0 ) )