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: dfib.c,v 1.12 2007/10/19 13:09:26 zerbino Exp $
43 #define HEAPBLOCKSIZE 1000
44 static int dfh_comparedata ( DFibHeap
* h
, Time key
, unsigned int data
, DFibHeapNode
* b
);
45 static DFibHeapNode
* allocateDFibHeapNode ( DFibHeap
* heap
)
47 return ( DFibHeapNode
* ) getItem ( heap
->nodeMemory
);
50 static void deallocateDFibHeapNode ( DFibHeapNode
* a
, DFibHeap
* heap
)
52 returnItem ( heap
->nodeMemory
, a
);
55 IDnum
dfibheap_getSize ( DFibHeap
* heap
)
60 #define swap(type, a, b) \
68 #define INT_BITS (sizeof(IDnum) * 8)
70 static inline IDnum
ceillog2 ( IDnum a
)
83 cons
= ( ( IDnum
) 1 ) << b
;
98 if ( ( ( ( IDnum
) 1 << i
) ) == oa
)
109 * Public Heap Functions
111 DFibHeap
* dfh_makekeyheap ()
115 if ( ( n
= malloc ( sizeof * n
) ) == NULL
)
120 n
->nodeMemory
= createMem_manager ( HEAPBLOCKSIZE
, sizeof ( DFibHeapNode
) );
129 void dfh_deleteheap ( DFibHeap
* h
)
131 fprintf ( stderr
, "DFibHeap: %lld node(s) allocated.\n", h
->nodeMemory
->counter
);
132 freeMem_manager ( h
->nodeMemory
);
133 h
->nodeMemory
= NULL
;
135 if ( h
->dfh_cons
!= NULL
)
137 free ( h
->dfh_cons
);
144 * Public Key Heap Functions
146 DFibHeapNode
* dfh_insertkey ( DFibHeap
* h
, Time key
, unsigned int data
)
150 if ( ( x
= dfhe_newelem ( h
) ) == NULL
)
155 /* just insert on root list, and make sure it's not the new min */
158 dfh_insertel ( h
, x
);
162 Time
dfh_replacekey ( DFibHeap
* h
, DFibHeapNode
* x
, Time key
)
166 ( void ) dfh_replacekeydata ( h
, x
, key
, x
->dfhe_data
);
170 unsigned int minInDHeap ( DFibHeap
* h
)
174 return h
->dfh_min
->dfhe_data
;
182 boolean
HasMin ( DFibHeap
* h
)
194 unsigned int dfh_replacekeydata ( DFibHeap
* h
, DFibHeapNode
* x
, Time key
, unsigned int data
)
200 odata
= x
->dfhe_data
;
204 * we can increase a key by deleting and reinserting, that
205 * requires O(lgn) time.
207 if ( ( r
= dfh_comparedata ( h
, key
, data
, x
) ) > 0 )
209 /* XXX - bad code! */
216 /* because they are equal, we don't have to do anything */
229 if ( y
!= NULL
&& dfh_compare ( h
, x
, y
) <= 0 )
232 dfh_cascading_cut ( h
, y
);
236 * the = is so that the call from dfh_delete will delete the proper
239 if ( dfh_compare ( h
, x
, h
->dfh_min
) <= 0 )
248 * Public void * Heap Functions
251 * this will return these values:
252 * NULL failed for some reason
253 * ptr token to use for manipulation of data
255 unsigned int dfh_extractmin ( DFibHeap
* h
)
261 if ( h
->dfh_min
!= NULL
)
263 z
= dfh_extractminel ( h
);
265 deallocateDFibHeapNode ( z
, h
);
271 unsigned int dfh_replacedata ( DFibHeapNode
* x
, unsigned int data
)
273 unsigned int odata
= x
->dfhe_data
;
274 //printf("replace node value %d with %d\n",x->dfhe_data,data);
279 unsigned int dfh_delete ( DFibHeap
* h
, DFibHeapNode
* x
)
282 //printf("destroy node %d in dheap\n",x->dfhe_data);
284 dfh_replacekey ( h
, x
, INT_MIN
);
285 dfh_extractmin ( h
);
290 * begin of private element fuctions
292 static DFibHeapNode
* dfh_extractminel ( DFibHeap
* h
)
295 DFibHeapNode
* x
, *y
, *orig
;
299 /* put all the children on the root list */
300 /* for true consistancy, we should use dfhe_remove */
301 for ( x
= ret
->dfhe_child
; x
!= orig
&& x
!= NULL
; )
310 dfh_insertrootlist ( h
, x
);
314 /* remove minimum from root list */
315 dfh_removerootlist ( h
, ret
);
318 /* if we aren't empty, consolidate the heap */
325 h
->dfh_min
= ret
->dfhe_right
;
326 dfh_consolidate ( h
);
332 static void dfh_insertrootlist ( DFibHeap
* h
, DFibHeapNode
* x
)
334 if ( h
->dfh_root
== NULL
)
342 dfhe_insertafter ( h
->dfh_root
, x
);
345 static void dfh_removerootlist ( DFibHeap
* h
, DFibHeapNode
* x
)
347 if ( x
->dfhe_left
== x
)
353 h
->dfh_root
= dfhe_remove ( x
);
357 static void dfh_consolidate ( DFibHeap
* h
)
367 /* assign a the value of h->dfh_cons so I don't have to rewrite code */
371 for ( i
= 0; i
< D
; i
++ )
376 while ( ( w
= h
->dfh_root
) != NULL
)
379 dfh_removerootlist ( h
, w
);
382 /* XXX - assert that d < D */
383 while ( a
[d
] != NULL
)
387 if ( dfh_compare ( h
, x
, y
) > 0 )
389 swap ( DFibHeapNode
*, x
, y
);
392 dfh_heaplink ( h
, y
, x
);
402 for ( i
= 0; i
< D
; i
++ )
405 dfh_insertrootlist ( h
, a
[i
] );
407 if ( h
->dfh_min
== NULL
|| dfh_compare ( h
, a
[i
], h
->dfh_min
) < 0 )
414 static void dfh_heaplink ( DFibHeap
* h
, DFibHeapNode
* y
, DFibHeapNode
* x
)
416 /* make y a child of x */
417 if ( x
->dfhe_child
== NULL
)
423 dfhe_insertbefore ( x
->dfhe_child
, y
);
431 static void dfh_cut ( DFibHeap
* h
, DFibHeapNode
* x
, DFibHeapNode
* y
)
435 dfh_insertrootlist ( h
, x
);
440 static void dfh_cascading_cut ( DFibHeap
* h
, DFibHeapNode
* y
)
444 while ( ( z
= y
->dfhe_p
) != NULL
)
446 if ( y
->dfhe_mark
== 0 )
460 * begining of handling elements of dfibheap
462 static DFibHeapNode
* dfhe_newelem ( DFibHeap
* h
)
466 if ( ( e
= allocateDFibHeapNode ( h
) ) == NULL
)
474 e
->dfhe_child
= NULL
;
481 static void dfhe_insertafter ( DFibHeapNode
* a
, DFibHeapNode
* b
)
483 if ( a
== a
->dfhe_right
)
492 b
->dfhe_right
= a
->dfhe_right
;
493 a
->dfhe_right
->dfhe_left
= b
;
499 static inline void dfhe_insertbefore ( DFibHeapNode
* a
, DFibHeapNode
* b
)
501 dfhe_insertafter ( a
->dfhe_left
, b
);
504 static DFibHeapNode
* dfhe_remove ( DFibHeapNode
* x
)
508 if ( x
== x
->dfhe_left
)
517 /* fix the parent pointer */
518 if ( x
->dfhe_p
!= NULL
&& x
->dfhe_p
->dfhe_child
== x
)
520 x
->dfhe_p
->dfhe_child
= ret
;
523 x
->dfhe_right
->dfhe_left
= x
->dfhe_left
;
524 x
->dfhe_left
->dfhe_right
= x
->dfhe_right
;
525 /* clear out hanging pointers */
532 static void dfh_checkcons ( DFibHeap
* h
)
536 /* make sure we have enough memory allocated to "reorganize" */
537 if ( h
->dfh_Dl
== -1 || h
->dfh_n
> ( 1 << h
->dfh_Dl
) )
541 if ( ( h
->dfh_Dl
= ceillog2 ( h
->dfh_n
) + 1 ) < 8 )
546 if ( oDl
!= h
->dfh_Dl
)
547 { h
->dfh_cons
= ( DFibHeapNode
** ) realloc ( h
->dfh_cons
, sizeof * h
->dfh_cons
* ( h
->dfh_Dl
+ 1 ) ); }
549 if ( h
->dfh_cons
== NULL
)
556 static int dfh_compare ( DFibHeap
* h
, DFibHeapNode
* a
, DFibHeapNode
* b
)
558 if ( a
->dfhe_key
< b
->dfhe_key
)
563 if ( a
->dfhe_key
== b
->dfhe_key
)
571 static int dfh_comparedata ( DFibHeap
* h
, Time key
, unsigned int data
, DFibHeapNode
* b
)
576 return dfh_compare ( h
, &a
, b
);
579 static void dfh_insertel ( DFibHeap
* h
, DFibHeapNode
* x
)
581 dfh_insertrootlist ( h
, x
);
583 if ( h
->dfh_min
== NULL
|| x
->dfhe_key
< h
->dfh_min
->dfhe_key
)
591 Time
dfibheap_el_getKey ( DFibHeapNode
* node
)
593 return node
->dfhe_key
;