/* Return the array position of the smaller child of the element at the postion i, or i itself if it's the smallest. Return -1 if i is a leaf. Checks if the children are valid, but not i itself. */ int smaller_child(heap *h, unsigned i) { unsigned i_lc=childl(i); unsigned i_rc=childr(i); if (is_valid_ind(h, i_lc) && is_valid_ind(h, i_rc)) { return smallest_el(h, i, smallest_el(h, i_lc, i_rc)); } else if (is_valid_ind(h, i_lc)) { return smallest_el(h, i, i_lc); } else if (is_valid_ind(h, i_rc)) { return smallest_el(h, i, i_rc); } else { return -1; } }
/** * Bubbles an element of the heap downwards into a position where it satisfies * the max-heap property. */ void heap_bubbledown(struct heap *heap, size_t ix) { void *elem, *child; size_t lim, last; assert(heap); if (heap->nelems < 2) return; /* nothing to bubble down */ if (ix > heap->nelems) return; /* index is out of bounds */ last = heap->nelems - 1; /* the limiting element is the last element with children and the * only element that may have fewer than two children */ lim = parent(last); elem = offset(heap, ix); /* here we handle the traversal through * heap elements linked to children */ while (ix < lim) { void *other; size_t cix; /* since we have not yet reached the limit element, we know that each * parent we encounter will have two children */ cix = childl(ix); child = offset(heap, cix); other = succ(heap, child); /* we pick the greater child to ensure that this subheap will satisfy * the heap property after we rearrange its elements */ if (compare(heap, child, other) < 0) { ++cix; child = other; } /* if we satisfy the heap property, we are done */ if (compare(heap, elem, child) >= 0) return; /* otherwise, we reorder the element with its greater child * and continue restoring the heap property */ swap(heap, elem, child); ix = cix; elem = child; } if (ix > lim) return; /* element has no child and is at its correct index */ /* if we have not yet returned, we know our current element is the limiting * element and that the last element is a child of the limiting element */ child = offset(heap, last); /* if nelems is odd, the final subtree has two children */ if (heap->nelems & 1) { void *other; other = pred(heap, child); if (compare(heap, child, other) < 0) child = other; } /* to fully restore the heap property, * we swap this element into place and are done */ if (compare(heap, elem, child) < 0) swap(heap, elem, child); }