89 */ |
91 */ |
90 |
92 |
91 #define BINARY_HEAP_BLOCKSIZE (1 << BINARY_HEAP_BLOCKSIZE_BITS) |
93 #define BINARY_HEAP_BLOCKSIZE (1 << BINARY_HEAP_BLOCKSIZE_BITS) |
92 #define BINARY_HEAP_BLOCKSIZE_MASK (BINARY_HEAP_BLOCKSIZE - 1) |
94 #define BINARY_HEAP_BLOCKSIZE_MASK (BINARY_HEAP_BLOCKSIZE - 1) |
93 |
95 |
94 // To make our life easy, we make the next define |
96 /* To make our life easy, we make the next define |
95 // Because Binary Heaps works with array from 1 to n, |
97 * Because Binary Heaps works with array from 1 to n, |
96 // and C with array from 0 to n-1, and we don't like typing |
98 * and C with array from 0 to n-1, and we don't like typing |
97 // q->data.binaryheap.elements[i - 1] every time, we use this define. |
99 * q->data.binaryheap.elements[i - 1] every time, we use this define. */ |
98 #define BIN_HEAP_ARR(i) q->data.binaryheap.elements[((i) - 1) >> BINARY_HEAP_BLOCKSIZE_BITS][((i) - 1) & BINARY_HEAP_BLOCKSIZE_MASK] |
100 #define BIN_HEAP_ARR(i) q->data.binaryheap.elements[((i) - 1) >> BINARY_HEAP_BLOCKSIZE_BITS][((i) - 1) & BINARY_HEAP_BLOCKSIZE_MASK] |
99 |
101 |
100 static void BinaryHeap_Clear(Queue* q, bool free_values) |
102 static void BinaryHeap_Clear(Queue* q, bool free_values) |
101 { |
103 { |
102 /* Free all items if needed and free all but the first blocks of memory */ |
104 /* Free all items if needed and free all but the first blocks of memory */ |
158 #ifdef QUEUE_DEBUG |
160 #ifdef QUEUE_DEBUG |
159 printf("[BinaryHeap] Increasing size of elements to %d nodes\n", q->data.binaryheap.blocks * BINARY_HEAP_BLOCKSIZE); |
161 printf("[BinaryHeap] Increasing size of elements to %d nodes\n", q->data.binaryheap.blocks * BINARY_HEAP_BLOCKSIZE); |
160 #endif |
162 #endif |
161 } |
163 } |
162 |
164 |
163 // Add the item at the end of the array |
165 /* Add the item at the end of the array */ |
164 BIN_HEAP_ARR(q->data.binaryheap.size + 1).priority = priority; |
166 BIN_HEAP_ARR(q->data.binaryheap.size + 1).priority = priority; |
165 BIN_HEAP_ARR(q->data.binaryheap.size + 1).item = item; |
167 BIN_HEAP_ARR(q->data.binaryheap.size + 1).item = item; |
166 q->data.binaryheap.size++; |
168 q->data.binaryheap.size++; |
167 |
169 |
168 // Now we are going to check where it belongs. As long as the parent is |
170 /* Now we are going to check where it belongs. As long as the parent is |
169 // bigger, we switch with the parent |
171 * bigger, we switch with the parent */ |
170 { |
172 { |
171 BinaryHeapNode temp; |
173 BinaryHeapNode temp; |
172 int i; |
174 int i; |
173 int j; |
175 int j; |
174 |
176 |
175 i = q->data.binaryheap.size; |
177 i = q->data.binaryheap.size; |
176 while (i > 1) { |
178 while (i > 1) { |
177 // Get the parent of this object (divide by 2) |
179 /* Get the parent of this object (divide by 2) */ |
178 j = i / 2; |
180 j = i / 2; |
179 // Is the parent bigger then the current, switch them |
181 /* Is the parent bigger then the current, switch them */ |
180 if (BIN_HEAP_ARR(i).priority <= BIN_HEAP_ARR(j).priority) { |
182 if (BIN_HEAP_ARR(i).priority <= BIN_HEAP_ARR(j).priority) { |
181 temp = BIN_HEAP_ARR(j); |
183 temp = BIN_HEAP_ARR(j); |
182 BIN_HEAP_ARR(j) = BIN_HEAP_ARR(i); |
184 BIN_HEAP_ARR(j) = BIN_HEAP_ARR(i); |
183 BIN_HEAP_ARR(i) = temp; |
185 BIN_HEAP_ARR(i) = temp; |
184 i = j; |
186 i = j; |
185 } else { |
187 } else { |
186 // It is not, we're done! |
188 /* It is not, we're done! */ |
187 break; |
189 break; |
188 } |
190 } |
189 } |
191 } |
190 } |
192 } |
191 |
193 |
198 |
200 |
199 #ifdef QUEUE_DEBUG |
201 #ifdef QUEUE_DEBUG |
200 printf("[BinaryHeap] Deleting an element. There are %d elements left\n", q->data.binaryheap.size); |
202 printf("[BinaryHeap] Deleting an element. There are %d elements left\n", q->data.binaryheap.size); |
201 #endif |
203 #endif |
202 |
204 |
203 // First, we try to find the item.. |
205 /* First, we try to find the item.. */ |
204 do { |
206 do { |
205 if (BIN_HEAP_ARR(i + 1).item == item) break; |
207 if (BIN_HEAP_ARR(i + 1).item == item) break; |
206 i++; |
208 i++; |
207 } while (i < q->data.binaryheap.size); |
209 } while (i < q->data.binaryheap.size); |
208 // We did not find the item, so we return false |
210 /* We did not find the item, so we return false */ |
209 if (i == q->data.binaryheap.size) return false; |
211 if (i == q->data.binaryheap.size) return false; |
210 |
212 |
211 // Now we put the last item over the current item while decreasing the size of the elements |
213 /* Now we put the last item over the current item while decreasing the size of the elements */ |
212 q->data.binaryheap.size--; |
214 q->data.binaryheap.size--; |
213 BIN_HEAP_ARR(i + 1) = BIN_HEAP_ARR(q->data.binaryheap.size + 1); |
215 BIN_HEAP_ARR(i + 1) = BIN_HEAP_ARR(q->data.binaryheap.size + 1); |
214 |
216 |
215 // Now the only thing we have to do, is resort it.. |
217 /* Now the only thing we have to do, is resort it.. |
216 // On place i there is the item to be sorted.. let's start there |
218 * On place i there is the item to be sorted.. let's start there */ |
217 { |
219 { |
218 uint j; |
220 uint j; |
219 BinaryHeapNode temp; |
221 BinaryHeapNode temp; |
220 /* Because of the fact that Binary Heap uses array from 1 to n, we need to |
222 /* Because of the fact that Binary Heap uses array from 1 to n, we need to |
221 * increase i by 1 |
223 * increase i by 1 |
222 */ |
224 */ |
223 i++; |
225 i++; |
224 |
226 |
225 for (;;) { |
227 for (;;) { |
226 j = i; |
228 j = i; |
227 // Check if we have 2 childs |
229 /* Check if we have 2 childs */ |
228 if (2 * j + 1 <= q->data.binaryheap.size) { |
230 if (2 * j + 1 <= q->data.binaryheap.size) { |
229 // Is this child smaller than the parent? |
231 /* Is this child smaller than the parent? */ |
230 if (BIN_HEAP_ARR(j).priority >= BIN_HEAP_ARR(2 * j).priority) i = 2 * j; |
232 if (BIN_HEAP_ARR(j).priority >= BIN_HEAP_ARR(2 * j).priority) i = 2 * j; |
231 // Yes, we _need_ to use i here, not j, because we want to have the smallest child |
233 /* Yes, we _need_ to use i here, not j, because we want to have the smallest child |
232 // This way we get that straight away! |
234 * This way we get that straight away! */ |
233 if (BIN_HEAP_ARR(i).priority >= BIN_HEAP_ARR(2 * j + 1).priority) i = 2 * j + 1; |
235 if (BIN_HEAP_ARR(i).priority >= BIN_HEAP_ARR(2 * j + 1).priority) i = 2 * j + 1; |
234 // Do we have one child? |
236 /* Do we have one child? */ |
235 } else if (2 * j <= q->data.binaryheap.size) { |
237 } else if (2 * j <= q->data.binaryheap.size) { |
236 if (BIN_HEAP_ARR(j).priority >= BIN_HEAP_ARR(2 * j).priority) i = 2 * j; |
238 if (BIN_HEAP_ARR(j).priority >= BIN_HEAP_ARR(2 * j).priority) i = 2 * j; |
237 } |
239 } |
238 |
240 |
239 // One of our childs is smaller than we are, switch |
241 /* One of our childs is smaller than we are, switch */ |
240 if (i != j) { |
242 if (i != j) { |
241 temp = BIN_HEAP_ARR(j); |
243 temp = BIN_HEAP_ARR(j); |
242 BIN_HEAP_ARR(j) = BIN_HEAP_ARR(i); |
244 BIN_HEAP_ARR(j) = BIN_HEAP_ARR(i); |
243 BIN_HEAP_ARR(i) = temp; |
245 BIN_HEAP_ARR(i) = temp; |
244 } else { |
246 } else { |
245 // None of our childs is smaller, so we stay here.. stop :) |
247 /* None of our childs is smaller, so we stay here.. stop :) */ |
246 break; |
248 break; |
247 } |
249 } |
248 } |
250 } |
249 } |
251 } |
250 |
252 |
259 printf("[BinaryHeap] Popping an element. There are %d elements left\n", q->data.binaryheap.size); |
261 printf("[BinaryHeap] Popping an element. There are %d elements left\n", q->data.binaryheap.size); |
260 #endif |
262 #endif |
261 |
263 |
262 if (q->data.binaryheap.size == 0) return NULL; |
264 if (q->data.binaryheap.size == 0) return NULL; |
263 |
265 |
264 // The best item is always on top, so give that as result |
266 /* The best item is always on top, so give that as result */ |
265 result = BIN_HEAP_ARR(1).item; |
267 result = BIN_HEAP_ARR(1).item; |
266 // And now we should get rid of this item... |
268 /* And now we should get rid of this item... */ |
267 BinaryHeap_Delete(q, BIN_HEAP_ARR(1).item, BIN_HEAP_ARR(1).priority); |
269 BinaryHeap_Delete(q, BIN_HEAP_ARR(1).item, BIN_HEAP_ARR(1).priority); |
268 |
270 |
269 return result; |
271 return result; |
270 } |
272 } |
271 |
273 |
277 q->del = BinaryHeap_Delete; |
279 q->del = BinaryHeap_Delete; |
278 q->clear = BinaryHeap_Clear; |
280 q->clear = BinaryHeap_Clear; |
279 q->free = BinaryHeap_Free; |
281 q->free = BinaryHeap_Free; |
280 q->data.binaryheap.max_size = max_size; |
282 q->data.binaryheap.max_size = max_size; |
281 q->data.binaryheap.size = 0; |
283 q->data.binaryheap.size = 0; |
282 // We malloc memory in block of BINARY_HEAP_BLOCKSIZE |
284 /* We malloc memory in block of BINARY_HEAP_BLOCKSIZE |
283 // It autosizes when it runs out of memory |
285 * It autosizes when it runs out of memory */ |
284 q->data.binaryheap.elements = CallocT<BinaryHeapNode*>((max_size - 1) / BINARY_HEAP_BLOCKSIZE + 1); |
286 q->data.binaryheap.elements = CallocT<BinaryHeapNode*>((max_size - 1) / BINARY_HEAP_BLOCKSIZE + 1); |
285 q->data.binaryheap.elements[0] = MallocT<BinaryHeapNode>(BINARY_HEAP_BLOCKSIZE); |
287 q->data.binaryheap.elements[0] = MallocT<BinaryHeapNode>(BINARY_HEAP_BLOCKSIZE); |
286 q->data.binaryheap.blocks = 1; |
288 q->data.binaryheap.blocks = 1; |
287 #ifdef QUEUE_DEBUG |
289 #ifdef QUEUE_DEBUG |
288 printf("[BinaryHeap] Initial size of elements is %d nodes\n", BINARY_HEAP_BLOCKSIZE); |
290 printf("[BinaryHeap] Initial size of elements is %d nodes\n", BINARY_HEAP_BLOCKSIZE); |
426 } |
428 } |
427 } |
429 } |
428 h->size = 0; |
430 h->size = 0; |
429 } |
431 } |
430 |
432 |
431 /* Finds the node that that saves this key pair. If it is not |
433 /** Finds the node that that saves this key pair. If it is not |
432 * found, returns NULL. If it is found, *prev is set to the |
434 * found, returns NULL. If it is found, *prev is set to the |
433 * node before the one found, or if the node found was the first in the bucket |
435 * node before the one found, or if the node found was the first in the bucket |
434 * to NULL. If it is not found, *prev is set to the last HashNode in the |
436 * to NULL. If it is not found, *prev is set to the last HashNode in the |
435 * bucket, or NULL if it is empty. prev can also be NULL, in which case it is |
437 * bucket, or NULL if it is empty. prev can also be NULL, in which case it is |
436 * not used for output. |
438 * not used for output. |