4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996 Thomas Nau
6 * Copyright (C) 1998,1999,2000,2001 harry eaton
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * Contact addresses for paper mail and Email:
23 * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA
24 * haceaton@aplcomm.jhuapl.edu
28 /* this file, heap.c, was written and is
29 * Copyright (c) 2001 C. Scott Ananian.
32 /* operations on heaps.
45 #ifdef HAVE_LIBDMALLOC
49 /* define this for more thorough self-checking of data structures */
50 #undef SLOW_ASSERTIONS
52 /* ---------------------------------------------------------------------------
53 * some local prototypes
56 /* ---------------------------------------------------------------------------
66 struct heap_element
*element
;
70 /* ---------------------------------------------------------------------------
71 * some local identifiers
73 static cost_t MIN_COST
= 0;
75 /* ---------------------------------------------------------------------------
78 /* helper functions for assertions */
80 #ifdef SLOW_ASSERTIONS
82 __heap_is_good_slow (heap_t
* heap
)
85 /* heap condition: key in each node should be smaller than in its children */
86 /* alternatively (and this is what we check): key in each node should be
87 * larger than (or equal to) key of its parent. */
88 /* note that array element[0] is not used (except as a sentinel) */
89 for (i
= 2; i
< heap
->size
; i
++)
90 if (heap
->element
[i
].cost
< heap
->element
[i
/ 2].cost
)
94 #endif /* SLOW_ASSERTIONS */
96 __heap_is_good (heap_t
* heap
)
98 return heap
&& (heap
->max
== 0 || heap
->element
) &&
99 (heap
->max
>= 0) && (heap
->size
>= 0) &&
100 (heap
->max
== 0 || heap
->size
< heap
->max
) &&
101 #ifdef SLOW_ASSERTIONS
102 __heap_is_good_slow (heap
) &&
106 #endif /* ! NDEBUG */
108 /* create an empty heap */
113 /* initialize MIN_COST if necessary */
116 assert (MIN_COST
< 0);
117 /* okay, create empty heap */
118 heap
= (heap_t
*)calloc (1, sizeof (*heap
));
120 assert (__heap_is_good (heap
));
126 heap_destroy (heap_t
** heap
)
128 assert (heap
&& *heap
);
129 assert (__heap_is_good (*heap
));
130 if ((*heap
)->element
)
131 free ((*heap
)->element
);
136 /* free all elements in the heap */
137 void heap_free (heap_t
*heap
, void (*freefunc
) (void *))
140 assert (__heap_is_good (heap
));
141 for ( ; heap
->size
; heap
->size
--)
143 if (heap
->element
[heap
->size
].data
)
144 freefunc (heap
->element
[heap
->size
].data
);
150 __upheap (heap_t
* heap
, int k
)
152 struct heap_element v
;
154 assert (heap
&& heap
->size
< heap
->max
);
155 assert (k
<= heap
->size
);
157 heap
->element
[0].cost
= MIN_COST
;
158 for (v
= heap
->element
[k
]; heap
->element
[k
/ 2].cost
> v
.cost
; k
= k
/ 2)
159 heap
->element
[k
] = heap
->element
[k
/ 2];
160 heap
->element
[k
] = v
;
164 heap_insert (heap_t
* heap
, cost_t cost
, void *data
)
166 assert (heap
&& __heap_is_good (heap
));
167 assert (cost
>= MIN_COST
);
169 /* determine whether we need to grow the heap */
170 if (heap
->size
+ 1 >= heap
->max
)
174 heap
->max
= 256; /* default initial heap size */
176 (struct heap_element
*)realloc (heap
->element
, heap
->max
* sizeof (*heap
->element
));
179 assert (heap
->size
< heap
->max
);
180 heap
->element
[heap
->size
].cost
= cost
;
181 heap
->element
[heap
->size
].data
= data
;
182 __upheap (heap
, heap
->size
); /* fix heap condition violation */
183 assert (__heap_is_good (heap
));
187 /* this procedure moves down the heap, exchanging the node at position
188 * k with the smaller of its two children as necessary and stopping when
189 * the node at k is smaller than both children or the bottom is reached.
192 __downheap (heap_t
* heap
, int k
)
194 struct heap_element v
;
196 assert (heap
&& heap
->size
< heap
->max
);
197 assert (k
<= heap
->size
);
199 v
= heap
->element
[k
];
200 while (k
<= heap
->size
/ 2)
203 if (j
< heap
->size
&& heap
->element
[j
].cost
> heap
->element
[j
+ 1].cost
)
205 if (v
.cost
< heap
->element
[j
].cost
)
207 heap
->element
[k
] = heap
->element
[j
];
210 heap
->element
[k
] = v
;
214 heap_remove_smallest (heap_t
* heap
)
216 struct heap_element v
;
217 assert (heap
&& __heap_is_good (heap
));
218 assert (heap
->size
> 0);
219 assert (heap
->max
> 1);
221 v
= heap
->element
[1];
222 heap
->element
[1] = heap
->element
[heap
->size
--];
224 __downheap (heap
, 1);
226 assert (__heap_is_good (heap
));
231 heap_replace (heap_t
* heap
, cost_t cost
, void *data
)
233 assert (heap
&& __heap_is_good (heap
));
235 if (heap_is_empty (heap
))
238 assert (heap
->size
> 0);
239 assert (heap
->max
> 1);
241 heap
->element
[0].cost
= cost
;
242 heap
->element
[0].data
= data
;
243 __downheap (heap
, 0); /* ooh, tricky! */
245 assert (__heap_is_good (heap
));
246 return heap
->element
[0].data
;
249 /* -- interrogation -- */
251 heap_is_empty (heap_t
* heap
)
253 assert (__heap_is_good (heap
));
254 return heap
->size
== 0;
259 heap_size (heap_t
* heap
)
261 assert (__heap_is_good (heap
));