2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1997-2001 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: heap.c,v 1.28.2.1 2004/03/09 06:11:46 marka Exp $ */
21 * Heap implementation of priority queues adapted from the following:
23 * _Introduction to Algorithms_, Cormen, Leiserson, and Rivest,
24 * MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7.
26 * _Algorithms_, Second Edition, Sedgewick, Addison-Wesley, 1988,
27 * ISBN 0-201-06673-4, chapter 11.
33 #include <isc/magic.h>
35 #include <isc/string.h> /* Required for memcpy. */
39 * Note: to make heap_parent and heap_left easy to compute, the first
40 * element of the heap array is not used; i.e. heap subscripts are 1-based,
43 #define heap_parent(i) ((i) >> 1)
44 #define heap_left(i) ((i) << 1)
46 #define SIZE_INCREMENT 1024
48 #define HEAP_MAGIC ISC_MAGIC('H', 'E', 'A', 'P')
49 #define VALID_HEAP(h) ISC_MAGIC_VALID(h, HEAP_MAGIC)
52 * When the heap is in a consistent state, the following invariant
53 * holds true: for every element i > 1, heap_parent(i) has a priority
54 * higher than or equal to that of i.
56 #define HEAPCONDITION(i) ((i) == 1 || \
57 ! heap->compare(heap->array[(i)], \
58 heap->array[heap_parent(i)]))
64 unsigned int size_increment
;
67 isc_heapcompare_t compare
;
68 isc_heapindex_t index
;
72 isc_heap_create(isc_mem_t
*mctx
, isc_heapcompare_t compare
,
73 isc_heapindex_t index
, unsigned int size_increment
,
78 REQUIRE(heapp
!= NULL
&& *heapp
== NULL
);
79 REQUIRE(compare
!= NULL
);
81 heap
= isc_mem_get(mctx
, sizeof *heap
);
83 return (ISC_R_NOMEMORY
);
84 heap
->magic
= HEAP_MAGIC
;
87 if (size_increment
== 0)
88 heap
->size_increment
= SIZE_INCREMENT
;
90 heap
->size_increment
= size_increment
;
93 heap
->compare
= compare
;
98 return (ISC_R_SUCCESS
);
102 isc_heap_destroy(isc_heap_t
**heapp
) {
105 REQUIRE(heapp
!= NULL
);
107 REQUIRE(VALID_HEAP(heap
));
109 if (heap
->array
!= NULL
)
110 isc_mem_put(heap
->mctx
, heap
->array
,
111 heap
->size
* sizeof (void *));
113 isc_mem_put(heap
->mctx
, heap
, sizeof *heap
);
119 resize(isc_heap_t
*heap
) {
123 REQUIRE(VALID_HEAP(heap
));
125 new_size
= heap
->size
+ heap
->size_increment
;
126 new_array
= isc_mem_get(heap
->mctx
, new_size
* sizeof (void *));
127 if (new_array
== NULL
)
129 if (heap
->array
!= NULL
) {
130 memcpy(new_array
, heap
->array
, heap
->size
* sizeof (void *));
131 isc_mem_put(heap
->mctx
, heap
->array
,
132 heap
->size
* sizeof (void *));
134 heap
->size
= new_size
;
135 heap
->array
= new_array
;
141 float_up(isc_heap_t
*heap
, unsigned int i
, void *elt
) {
144 for (p
= heap_parent(i
);
145 i
> 1 && heap
->compare(elt
, heap
->array
[p
]);
146 i
= p
, p
= heap_parent(i
)) {
147 heap
->array
[i
] = heap
->array
[p
];
148 if (heap
->index
!= NULL
)
149 (heap
->index
)(heap
->array
[i
], i
);
151 heap
->array
[i
] = elt
;
152 if (heap
->index
!= NULL
)
153 (heap
->index
)(heap
->array
[i
], i
);
155 INSIST(HEAPCONDITION(i
));
159 sink_down(isc_heap_t
*heap
, unsigned int i
, void *elt
) {
160 unsigned int j
, size
, half_size
;
162 half_size
= size
/ 2;
163 while (i
<= half_size
) {
164 /* Find the smallest of the (at most) two children. */
166 if (j
< size
&& heap
->compare(heap
->array
[j
+1],
169 if (heap
->compare(elt
, heap
->array
[j
]))
171 heap
->array
[i
] = heap
->array
[j
];
172 if (heap
->index
!= NULL
)
173 (heap
->index
)(heap
->array
[i
], i
);
176 heap
->array
[i
] = elt
;
177 if (heap
->index
!= NULL
)
178 (heap
->index
)(heap
->array
[i
], i
);
180 INSIST(HEAPCONDITION(i
));
184 isc_heap_insert(isc_heap_t
*heap
, void *elt
) {
187 REQUIRE(VALID_HEAP(heap
));
190 if (heap
->last
>= heap
->size
&& !resize(heap
))
191 return (ISC_R_NOMEMORY
);
193 float_up(heap
, i
, elt
);
195 return (ISC_R_SUCCESS
);
199 isc_heap_delete(isc_heap_t
*heap
, unsigned int i
) {
203 REQUIRE(VALID_HEAP(heap
));
204 REQUIRE(i
>= 1 && i
<= heap
->last
);
206 if (i
== heap
->last
) {
209 elt
= heap
->array
[heap
->last
--];
210 less
= heap
->compare(elt
, heap
->array
[i
]);
211 heap
->array
[i
] = elt
;
213 float_up(heap
, i
, heap
->array
[i
]);
215 sink_down(heap
, i
, heap
->array
[i
]);
220 isc_heap_increased(isc_heap_t
*heap
, unsigned int i
) {
221 REQUIRE(VALID_HEAP(heap
));
222 REQUIRE(i
>= 1 && i
<= heap
->last
);
224 float_up(heap
, i
, heap
->array
[i
]);
228 isc_heap_decreased(isc_heap_t
*heap
, unsigned int i
) {
229 REQUIRE(VALID_HEAP(heap
));
230 REQUIRE(i
>= 1 && i
<= heap
->last
);
232 sink_down(heap
, i
, heap
->array
[i
]);
236 isc_heap_element(isc_heap_t
*heap
, unsigned int i
) {
237 REQUIRE(VALID_HEAP(heap
));
238 REQUIRE(i
>= 1 && i
<= heap
->last
);
240 return (heap
->array
[i
]);
244 isc_heap_foreach(isc_heap_t
*heap
, isc_heapaction_t action
, void *uap
) {
247 REQUIRE(VALID_HEAP(heap
));
248 REQUIRE(action
!= NULL
);
250 for (i
= 1; i
<= heap
->last
; i
++)
251 (action
)(heap
->array
[i
], uap
);