179 lines
3.7 KiB
C++
179 lines
3.7 KiB
C++
/****************************************************************************/
|
|
/*
|
|
Binary heap routines for use in Prim's algorithm,
|
|
with points are numbered from 0 to n-1
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include "heap.h"
|
|
#include "err.h"
|
|
|
|
namespace Flute {
|
|
|
|
Heap* _heap = (Heap*)NULL;
|
|
long _max_heap_size = 0;
|
|
long _heap_size = 0;
|
|
|
|
/****************************************************************************/
|
|
/*
|
|
*/
|
|
|
|
void allocate_heap( long n )
|
|
{
|
|
if( _max_heap_size < n )
|
|
{
|
|
_heap = (Heap*)realloc( (void*)_heap, (size_t)(n+1)*sizeof(Heap) );
|
|
if( ! _heap )
|
|
{
|
|
err_exit( "Cannot reallocate memory in allocate_heap!" );
|
|
}
|
|
_max_heap_size = n;
|
|
}
|
|
}
|
|
/****************************************************************************/
|
|
/*
|
|
*/
|
|
|
|
void deallocate_heap()
|
|
{
|
|
_max_heap_size = 0;
|
|
if( _heap )
|
|
{
|
|
free( (void*)_heap );
|
|
_heap = (Heap*)NULL;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void heap_init( long n )
|
|
{
|
|
register long p;
|
|
|
|
allocate_heap( n );
|
|
_heap_size = 0;
|
|
for( p = 0; p < n; p++ )
|
|
{
|
|
heap_idx( p ) = 0;
|
|
}
|
|
|
|
} /* END heap_init() */
|
|
|
|
/****************************************************************************/
|
|
|
|
void heap_insert(
|
|
long p,
|
|
long key
|
|
)
|
|
{
|
|
register long k; /* hole in the heap */
|
|
register long j; /* parent of the hole */
|
|
register long q; /* heap_elt(j) */
|
|
|
|
heap_key( p ) = key;
|
|
|
|
if( _heap_size == 0 )
|
|
{
|
|
_heap_size = 1;
|
|
heap_elt( 1 ) = p;
|
|
heap_idx( p ) = 1;
|
|
return;
|
|
}
|
|
|
|
k = ++ _heap_size;
|
|
j = k >> 1; /* k/2 */
|
|
|
|
while( (j > 0) && (heap_key(q=heap_elt(j)) > key) ) {
|
|
|
|
heap_elt( k ) = q;
|
|
heap_idx( q ) = k;
|
|
k = j;
|
|
j = k>>1; /* k/2 */
|
|
|
|
}
|
|
|
|
/* store p in the position of the hole */
|
|
heap_elt( k ) = p;
|
|
heap_idx( p ) = k;
|
|
|
|
} /* END heap_insert() */
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
void heap_decrease_key
|
|
(
|
|
long p,
|
|
long new_key
|
|
)
|
|
{
|
|
register long k; /* hole in the heap */
|
|
register long j; /* parent of the hole */
|
|
register long q; /* heap_elt(j) */
|
|
|
|
heap_key( p ) = new_key;
|
|
k = heap_idx( p );
|
|
j = k >> 1; /* k/2 */
|
|
|
|
if( (j > 0) && (heap_key(q=heap_elt(j)) > new_key) ) { /* change is needed */
|
|
do {
|
|
|
|
heap_elt( k ) = q;
|
|
heap_idx( q ) = k;
|
|
k = j;
|
|
j = k>>1; /* k/2 */
|
|
|
|
} while( (j > 0) && (heap_key(q=heap_elt(j)) > new_key) );
|
|
|
|
/* store p in the position of the hole */
|
|
heap_elt( k ) = p;
|
|
heap_idx( p ) = k;
|
|
}
|
|
|
|
} /* END heap_decrease_key() */
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
long heap_delete_min()
|
|
{
|
|
long min, last;
|
|
register long k; /* hole in the heap */
|
|
register long j; /* child of the hole */
|
|
register long l_key; /* key of last point */
|
|
|
|
if( _heap_size == 0 ) /* heap is empty */
|
|
return( -1 );
|
|
|
|
min = heap_elt( 1 );
|
|
last = heap_elt( _heap_size -- );
|
|
l_key = heap_key( last );
|
|
|
|
k = 1; j = 2;
|
|
while( j <= _heap_size ) {
|
|
|
|
if( heap_key(heap_elt(j)) > heap_key(heap_elt(j+1)) )
|
|
j++;
|
|
|
|
if( heap_key(heap_elt(j)) >= l_key)
|
|
break; /* found a position to insert 'last' */
|
|
|
|
/* else, sift hole down */
|
|
heap_elt(k) = heap_elt(j); /* Note that j <= _heap_size */
|
|
heap_idx( heap_elt(k) ) = k;
|
|
k = j;
|
|
j = k << 1;
|
|
}
|
|
|
|
heap_elt( k ) = last;
|
|
heap_idx( last ) = k;
|
|
|
|
heap_idx( min ) = -1; /* mark the point visited */
|
|
return( min );
|
|
|
|
} /* END heap_delete_min() */
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
} // namespace Flute
|