/* $Id: heap.c,v 1.1 2005/12/18 00:11:32 dj Exp $ */ /* * COPYRIGHT * * PCB, interactive printed circuit board design * Copyright (C) 1994,1995,1996 Thomas Nau * Copyright (C) 1998,1999,2000,2001 harry eaton * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Contact addresses for paper mail and Email: * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA * haceaton@aplcomm.jhuapl.edu * */ /* this file, heap.c, was written and is * Copyright (c) 2001 C. Scott Ananian. */ /* operations on heaps. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "global.h" #include #include "heap.h" #ifdef HAVE_LIBDMALLOC #include #endif RCSID("$Id: heap.c,v 1.1 2005/12/18 00:11:32 dj Exp $"); /* define this for more thorough self-checking of data structures */ #undef SLOW_ASSERTIONS /* --------------------------------------------------------------------------- * some local prototypes */ /* --------------------------------------------------------------------------- * some local types */ struct heap_element { cost_t cost; void *data; }; struct heap_struct { struct heap_element *element; int size, max; }; /* --------------------------------------------------------------------------- * some local identifiers */ static cost_t MIN_COST = 0; /* --------------------------------------------------------------------------- * functions. */ /* helper functions for assertions */ #ifndef NDEBUG #ifdef SLOW_ASSERTIONS static int __heap_is_good_slow (heap_t * heap) { int i; /* heap condition: key in each node should be smaller than in its children */ /* alternatively (and this is what we check): key in each node should be * larger than (or equal to) key of its parent. */ /* note that array element[0] is not used (except as a sentinel) */ for (i = 2; i < heap->size; i++) if (heap->element[i].cost < heap->element[i / 2].cost) return 0; return 1; } #endif /* SLOW_ASSERTIONS */ static int __heap_is_good (heap_t * heap) { return heap && (heap->max == 0 || heap->element) && (heap->max >= 0) && (heap->size >= 0) && (heap->max == 0 || heap->size < heap->max) && #ifdef SLOW_ASSERTIONS __heap_is_good_slow (heap) && #endif 1; } #endif /* ! NDEBUG */ /* create an empty heap */ heap_t * heap_create () { heap_t *heap; /* initialize MIN_COST if necessary */ if (MIN_COST == 0) MIN_COST = -1e23; assert (MIN_COST < 0); /* okay, create empty heap */ heap = calloc(1, sizeof (*heap)); assert (heap); assert (__heap_is_good (heap)); return heap; } /* destroy a heap */ void heap_destroy (heap_t ** heap) { assert (heap && *heap); assert (__heap_is_good (*heap)); if ((*heap)->element) free ((*heap)->element); free (*heap); *heap = NULL; } /* -- mutation -- */ static void __upheap (heap_t * heap, int k) { struct heap_element v; assert (heap && heap->size < heap->max); assert (k <= heap->size); v = heap->element[k]; heap->element[0].cost = MIN_COST; for (v = heap->element[k]; heap->element[k / 2].cost > v.cost; k = k / 2) heap->element[k] = heap->element[k / 2]; heap->element[k] = v; } void heap_insert (heap_t * heap, cost_t cost, void *data) { assert (heap && __heap_is_good (heap)); assert (cost >= MIN_COST); /* determine whether we need to grow the heap */ if (heap->size + 1 >= heap->max) { heap->max *= 2; if (heap->max == 0) heap->max = 32; /* default initial heap size */ heap->element = realloc (heap->element, heap->max * sizeof (*heap->element)); } heap->size++; assert (heap->size < heap->max); heap->element[heap->size].cost = cost; heap->element[heap->size].data = data; __upheap (heap, heap->size); /* fix heap condition violation */ assert (__heap_is_good (heap)); return; } /* this procedure moves down the heap, exchanging the node at position * k with the smaller of its two children as necessary and stopping when * the node at k is smaller than both children or the bottom is reached. */ static void __downheap (heap_t * heap, int k) { struct heap_element v; assert (heap && heap->size < heap->max); assert (k <= heap->size); v = heap->element[k]; while (k <= heap->size / 2) { int j = k + k; if (j < heap->size && heap->element[j].cost > heap->element[j + 1].cost) j++; if (v.cost < heap->element[j].cost) break; heap->element[k] = heap->element[j]; k = j; } heap->element[k] = v; } void * heap_remove_smallest (heap_t * heap) { struct heap_element v; assert (heap && __heap_is_good (heap)); assert (heap->size > 0); assert (heap->max > 1); v = heap->element[1]; heap->element[1] = heap->element[heap->size--]; if (heap->size > 0) __downheap (heap, 1); assert (__heap_is_good (heap)); return v.data; } void * heap_replace (heap_t * heap, cost_t cost, void *data) { assert (heap && __heap_is_good (heap)); if (heap_is_empty (heap)) return data; assert (heap->size > 0); assert (heap->max > 1); heap->element[0].cost = cost; heap->element[0].data = data; __downheap (heap, 0); /* ooh, tricky! */ assert (__heap_is_good (heap)); return heap->element[0].data; } /* -- interrogation -- */ int heap_is_empty (heap_t * heap) { assert (__heap_is_good (heap)); return heap->size == 0; }