From aca3db2b0661724d1acf94c9ee6b7a85bec826a0 Mon Sep 17 00:00:00 2001 From: "Justin R. Cutler" Date: Sat, 9 Apr 2016 11:39:19 -0400 Subject: [PATCH] Add heap_replace() functionality --- src/heap.c | 21 +++++++++++++++++++++ test/heap.c | 14 ++++++++++++-- threadless/heap.h | 9 +++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/heap.c b/src/heap.c index 9413bd6..a0d9758 100644 --- a/src/heap.c +++ b/src/heap.c @@ -84,6 +84,27 @@ int heap_push(heap_t *heap, heap_node_t *node) } +void heap_replace(heap_node_t *old, heap_node_t *node) +{ + heap_t *heap = old->heap; + size_t pos = old->index; + heap_node_t **storage = heap->allocation.memory; + + /* disassociate old node from heap */ + old->heap = NULL; + old->index = 0; + + /* place new node in heap */ + node->heap = heap; + node->index = pos; + storage[pos] = node; + + /* restore heap invariant */ + sift_up(heap, pos, heap->count); + sift_down(heap, 0, pos); +} + + void heap_remove(heap_node_t *node) { heap_t *heap = node->heap; diff --git a/test/heap.c b/test/heap.c index 991c783..c8023cd 100644 --- a/test/heap.c +++ b/test/heap.c @@ -30,7 +30,12 @@ #include -const int data[] = { 4 /* duplicate */, 1, 9, 2, 8, 4, 0, 5, 3, 6, 7, 99 }; +const int data[] = { + 4 /* duplicate (remove) */, + 6 /* duplicate (replace with 1) */, + 9, 2, 8, 4, 0, 5, 3, 6, 7, + 99 /* remove */, +}; const size_t data_count = sizeof(data) / sizeof(data[0]); @@ -58,7 +63,7 @@ static int run(allocator_t *allocator) heap_node_t *node; allocation_init(&alloc, allocator); - error = allocation_realloc_array(&alloc, data_count, sizeof(*values)); + error = allocation_realloc_array(&alloc, data_count + 1, sizeof(*values)); if (error) { return error; } @@ -74,9 +79,14 @@ static int run(allocator_t *allocator) /* remove from middle */ heap_remove(&(values[0].node)); + /* remove from end */ heap_remove(&(values[data_count - 1].node)); + /* replace */ + values[data_count].value = 1; + heap_replace(&(values[1].node), &(values[data_count].node)); + /* pull values out of heap (minimum first) */ while (NULL != (node = heap_pop(&heap))) { value_t *value = container_of(node, value_t, node); diff --git a/threadless/heap.h b/threadless/heap.h index ed0369a..a52ffb7 100644 --- a/threadless/heap.h +++ b/threadless/heap.h @@ -84,6 +84,15 @@ static inline heap_node_t *heap_peek(const heap_t *heap) */ int heap_push(heap_t *heap, heap_node_t *node); +/** Replace an existing @p old node in a heap with a new @p node + * @param[in,out] old old node + * @param[in,out] node new node + * @pre @p old must be in a heap + * @post @p old is no longer in a heap + * @post @p node is in the heap that previously contained @p old + */ +void heap_replace(heap_node_t *old, heap_node_t *node); + /** Remove an arbitrary @p node from its heap * @param[in,out] node node * @pre @p node must be in a heap