/* Complexity: O(log n) */ static void heapify_down(Heap *heap, unsigned long index) { unsigned long left, right, largest; int done; done = 0; while(!done) { left = left_child_of(index); right = right_child_of(index); largest = index; if(left < heap_size(heap) && heap->comparefn(darray_index(heap->h, left), darray_index(heap->h, index)) > 0) { largest = left; } if(right < heap_size(heap) && heap->comparefn(darray_index(heap->h, right), darray_index(heap->h, largest)) > 0) { largest = right; } if(largest != index) { darray_swap(heap->h, index, largest); index = largest; } else { done = 1; } } }
/* Complexity: O(n log n), worst-case if data is located * at the right-most leaf node on the lowest level of the * tree. */ int heap_remove(Heap *heap, const void *data) { unsigned long i; assert(heap != NULL); if(heap_is_empty(heap)) { return -1; } for(i = 0; i < heap_size(heap); i++) { if(darray_index(heap->h, i) == data) { if(darray_swap(heap->h, i, darray_size(heap->h) - 1) < 0) { return -1; } /* Don't care about the return value */ darray_remove(heap->h, darray_size(heap->h) - 1); heapify_down(heap, i); return 0; } } return -1; }
/* Complexity: O(log n) */ static void heapify_up(Heap *heap, unsigned long index) { while(index > 0 && heap->comparefn(darray_index(heap->h, index), darray_index(heap->h, parent_of(index))) > 0) { darray_swap(heap->h, index, parent_of(index)); index = parent_of(index); } }
/* @description: Sorts the darray pointed to by p according to the comparison rules specified within the function pointed to by cmp. If the sort could not be completed, false is returned. Otherwise, true is returned. */ extern bool darray_sort(darray *p, int (*cmp)(const void*, const void*)) { size_t n = p->capacity; size_t i = n / 2; /* Make the entire array a valid heap */ while (i-- > 0) { if (!do_heap(p, i, n, cmp)) return false; } while (--n < (size_t)-1) { /* Place the maximum value and fix the heap for remaining elements */ if (!darray_swap(p, 0, n) || !do_heap(p, 0, n, cmp)) return false; } return true; }
/* @description: A simple insertion sort. */ extern bool darray_insertion_sort(darray *d_array, int (*cmp)(const void*, const void*)) { size_t i, j; unsigned char *temp; for (i = 1; i < d_array->capacity; i++) { temp = &d_array->data[i * d_array->item_size]; // compare data j = i-1; while (cmp(temp, &d_array->data[j * d_array->item_size]) && j>=0) { darray_swap(d_array, j+1, j); j--; } memcpy(&d_array->data[(j+1) * d_array->item_size], &d_array->data[j * d_array->item_size], d_array->item_size); } return true; }
/* Complexity: O(log n) */ void* heap_pop(Heap *heap) { void *ret = NULL; assert(heap != NULL); if(heap_is_empty(heap)) { return NULL; } if(darray_swap(heap->h, 0, darray_size(heap->h) - 1) < 0) { return NULL; } ret = darray_remove(heap->h, darray_size(heap->h) - 1); heapify_down(heap, 0); return ret; }