2 * Copyright (c) 1998 - 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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
49 * Allocate a new heap of size `sz' with compare function `cmp'.
53 heap_new (unsigned sz
, heap_cmp_fn cmp
)
58 ret
= malloc (sizeof(*ret
));
65 ret
->data
= malloc (sz
* sizeof(*ret
->data
));
66 if (ret
->sz
!= 0 && ret
->data
== NULL
) {
70 for (i
= 0; i
< sz
; ++i
) {
71 ret
->data
[i
].data
= NULL
;
72 ret
->data
[i
].ptr
= NULL
;
77 static inline unsigned
80 return (n
+ 1) / 2 - 1;
83 static inline unsigned
84 left_child (unsigned n
)
89 static inline unsigned
90 right_child (unsigned n
)
95 static heap_ptr dummy
;
102 assign (Heap
*h
, unsigned n
, heap_element el
)
105 *(h
->data
[n
].ptr
) = n
;
113 upheap (Heap
*h
, unsigned n
)
115 heap_element v
= h
->data
[n
];
117 while (n
> 0 && (*h
->cmp
)(h
->data
[parent(n
)].data
, v
.data
) > 0) {
118 assign (h
, n
, h
->data
[parent(n
)]);
129 downheap (Heap
*h
, unsigned n
)
131 heap_element v
= h
->data
[n
];
133 while (n
< h
->sz
/ 2) {
137 assert (left_child(n
) < h
->sz
);
139 new_n
= left_child(n
);
141 cmp1
= (*h
->cmp
)(v
.data
, h
->data
[new_n
].data
);
143 if (right_child(n
) < h
->sz
) {
144 cmp2
= (*h
->cmp
)(v
.data
, h
->data
[right_child(n
)].data
);
147 new_n
= right_child(n
);
152 assign (h
, n
, h
->data
[new_n
]);
162 * Insert a new element `data' into `h'.
163 * Return 0 if succesful or else -1.
167 heap_insert (Heap
*h
, const void *data
, heap_ptr
*ptr
)
169 assert (data
!= NULL
);
171 if (h
->sz
== h
->max_sz
) {
172 unsigned new_sz
= h
->max_sz
* 2;
175 tmp
= realloc (h
->data
, new_sz
* sizeof(*h
->data
));
184 h
->data
[h
->sz
].data
= data
;
185 h
->data
[h
->sz
].ptr
= ptr
;
192 * Return the head of the heap `h' (or NULL if it's empty).
201 return h
->data
[0].data
;
205 * Remove element `n' from the heap `h'
209 remove_this (Heap
*h
, unsigned n
)
214 h
->data
[n
] = h
->data
[h
->sz
];
215 h
->data
[h
->sz
].data
= NULL
;
216 h
->data
[h
->sz
].ptr
= NULL
;
224 * Remove the head from the heap `h'.
228 heap_remove_head (Heap
*h
)
234 * Remove this very element from the heap `h'.
235 * Return 0 if succesful and -1 if it couldn't be found.
239 heap_remove (Heap
*h
, heap_ptr ptr
)
244 assert (h
->data
[ptr
].ptr
!= &dummy
);
246 remove_this (h
, ptr
);
251 * Delete the heap `h'
255 heap_delete (Heap
*h
)
266 do_verify (Heap
*h
, unsigned n
)
268 if (left_child(n
) < h
->sz
) {
269 if((*h
->cmp
)(h
->data
[n
].data
, h
->data
[left_child(n
)].data
) > 0)
271 if (!do_verify (h
, left_child(n
)))
274 if (right_child(n
) < h
->sz
) {
275 if((*h
->cmp
)(h
->data
[n
].data
, h
->data
[right_child(n
)].data
) > 0)
277 if (!do_verify (h
, right_child(n
)))
284 * Verify that `h' is really a heap.
288 heap_verify (Heap
*h
)
290 return do_verify (h
, 0);