6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996 Thomas Nau
8 * Copyright (C) 1998,1999,2000,2001 harry eaton
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * Contact addresses for paper mail and Email:
25 * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA
26 * haceaton@aplcomm.jhuapl.edu
30 /* this file, heap.c, was written and is
31 * Copyright (c) 2001 C. Scott Ananian.
34 /* operations on heaps.
47 #ifdef HAVE_LIBDMALLOC
54 /* define this for more thorough self-checking of data structures */
55 #undef SLOW_ASSERTIONS
57 /* ---------------------------------------------------------------------------
58 * some local prototypes
61 /* ---------------------------------------------------------------------------
71 struct heap_element
*element
;
75 /* ---------------------------------------------------------------------------
76 * some local identifiers
78 static cost_t MIN_COST
= 0;
80 /* ---------------------------------------------------------------------------
83 /* helper functions for assertions */
85 #ifdef SLOW_ASSERTIONS
87 __heap_is_good_slow (heap_t
* heap
)
90 /* heap condition: key in each node should be smaller than in its children */
91 /* alternatively (and this is what we check): key in each node should be
92 * larger than (or equal to) key of its parent. */
93 /* note that array element[0] is not used (except as a sentinel) */
94 for (i
= 2; i
< heap
->size
; i
++)
95 if (heap
->element
[i
].cost
< heap
->element
[i
/ 2].cost
)
99 #endif /* SLOW_ASSERTIONS */
101 __heap_is_good (heap_t
* heap
)
103 return heap
&& (heap
->max
== 0 || heap
->element
) &&
104 (heap
->max
>= 0) && (heap
->size
>= 0) &&
105 (heap
->max
== 0 || heap
->size
< heap
->max
) &&
106 #ifdef SLOW_ASSERTIONS
107 __heap_is_good_slow (heap
) &&
111 #endif /* ! NDEBUG */
113 /* create an empty heap */
118 /* initialize MIN_COST if necessary */
121 assert (MIN_COST
< 0);
122 /* okay, create empty heap */
123 heap
= calloc (1, sizeof (*heap
));
125 assert (__heap_is_good (heap
));
131 heap_destroy (heap_t
** heap
)
133 assert (heap
&& *heap
);
134 assert (__heap_is_good (*heap
));
135 if ((*heap
)->element
)
136 free ((*heap
)->element
);
141 /* free all elements in the heap */
142 void heap_free (heap_t
*heap
, void (*freefunc
) (void *))
145 assert (__heap_is_good (heap
));
146 for ( ; heap
->size
; heap
->size
--)
148 if (heap
->element
[heap
->size
].data
)
149 freefunc (heap
->element
[heap
->size
].data
);
155 __upheap (heap_t
* heap
, int k
)
157 struct heap_element v
;
159 assert (heap
&& heap
->size
< heap
->max
);
160 assert (k
<= heap
->size
);
162 v
= heap
->element
[k
];
163 heap
->element
[0].cost
= MIN_COST
;
164 for (v
= heap
->element
[k
]; heap
->element
[k
/ 2].cost
> v
.cost
; k
= k
/ 2)
165 heap
->element
[k
] = heap
->element
[k
/ 2];
166 heap
->element
[k
] = v
;
170 heap_insert (heap_t
* heap
, cost_t cost
, void *data
)
172 assert (heap
&& __heap_is_good (heap
));
173 assert (cost
>= MIN_COST
);
175 /* determine whether we need to grow the heap */
176 if (heap
->size
+ 1 >= heap
->max
)
180 heap
->max
= 256; /* default initial heap size */
182 realloc (heap
->element
, heap
->max
* sizeof (*heap
->element
));
185 assert (heap
->size
< heap
->max
);
186 heap
->element
[heap
->size
].cost
= cost
;
187 heap
->element
[heap
->size
].data
= data
;
188 __upheap (heap
, heap
->size
); /* fix heap condition violation */
189 assert (__heap_is_good (heap
));
193 /* this procedure moves down the heap, exchanging the node at position
194 * k with the smaller of its two children as necessary and stopping when
195 * the node at k is smaller than both children or the bottom is reached.
198 __downheap (heap_t
* heap
, int k
)
200 struct heap_element v
;
202 assert (heap
&& heap
->size
< heap
->max
);
203 assert (k
<= heap
->size
);
205 v
= heap
->element
[k
];
206 while (k
<= heap
->size
/ 2)
209 if (j
< heap
->size
&& heap
->element
[j
].cost
> heap
->element
[j
+ 1].cost
)
211 if (v
.cost
< heap
->element
[j
].cost
)
213 heap
->element
[k
] = heap
->element
[j
];
216 heap
->element
[k
] = v
;
220 heap_remove_smallest (heap_t
* heap
)
222 struct heap_element v
;
223 assert (heap
&& __heap_is_good (heap
));
224 assert (heap
->size
> 0);
225 assert (heap
->max
> 1);
227 v
= heap
->element
[1];
228 heap
->element
[1] = heap
->element
[heap
->size
--];
230 __downheap (heap
, 1);
232 assert (__heap_is_good (heap
));
237 heap_replace (heap_t
* heap
, cost_t cost
, void *data
)
239 assert (heap
&& __heap_is_good (heap
));
241 if (heap_is_empty (heap
))
244 assert (heap
->size
> 0);
245 assert (heap
->max
> 1);
247 heap
->element
[0].cost
= cost
;
248 heap
->element
[0].data
= data
;
249 __downheap (heap
, 0); /* ooh, tricky! */
251 assert (__heap_is_good (heap
));
252 return heap
->element
[0].data
;
255 /* -- interrogation -- */
257 heap_is_empty (heap_t
* heap
)
259 assert (__heap_is_good (heap
));
260 return heap
->size
== 0;
265 heap_size (heap_t
* heap
)
267 assert (__heap_is_good (heap
));