Best-case maximum deletion in a binary heap 2026-10-31
In the implementation that exchanges the root with the final leaf and then applies heapify down, a max-heap of size at least four with distinct keys requires at least one downward exchange: the old final leaf's parent remains and has a larger key. One downward exchange can suffice, even for large heaps, by promoting the opposite root child and letting the moved key dominate that child's descendants. Thus the best case is two pairwise exchanges when the initial root/final-leaf exchange is counted. This is a convention about that implementation: a hole-moving implementation uses assignments rather than pairwise exchanges, and the worst case still has logarithmic time complexity.
Heap data structure 2026-10-20
A tree-based data structure that orders each parent relative to its children so that an extremal value is available at the root. In a max-heap, every parent is at least as large as its children. Heap implementations provide one way to realize a priority queue; the abstract queue and its implementing structure are distinct concepts.
Heapsort 2026-10-31
Build a max-heap in an array, then repeatedly exchange its root with the last element of the active heap and restore heap order by heapify down. The inactive suffix grows in ascending order. Bottom-up heap construction costs because the number of nodes at height decreases geometrically, and the extraction phase costs . Iterative sifting uses constant auxiliary storage. Long-distance exchanges can reverse equal-key records, so the usual version does not provide stable sorting.
Maximum priority queue Created 2026-10-24 Updated 2026-10-31
A priority queue whose distinguished entry has largest key. A max-heap implements maximum inspection in constant time, and insertion, extraction of a maximum and increasing the key of a located entry in running time. An entry handle needs its current heap index to support that last bound; searching by an arbitrary key can take linear time. Multiple entries can have equal keys without requiring a particular tie order.
For heapsort, use the usual array representation of a max-heap, indexed from zero, with children . Build the max-heap from the last internal node towards the root, using heapify down. The three build stages are
start [2,7,3,2,8,1]
sift at index 2 [2,7,3,2,8,1]
sift at index 1 [2,8,3,2,7,1]
sift at index 0 [8,7,3,2,2,1]At index zero, the value
2 moves below 8 and then below 7. Next exchange the root with the last active element, shorten the active heap, and restore heap order. A vertical separator below distinguishes the active prefix from its sorted final suffix.| Removed maximum | After root exchange | After restoring heap order |
|---|---|---|
1,7,3,2,2 | 8 | 7,2,3,1,2 | 8 | |
2,2,3,1 | 7,8 | 3,2,2,1 | 7,8 | |
1,2,2 | 3,7,8 | 2,1,2 | 3,7,8 | |
2,1 | 2,3,7,8 | 2,1 | 2,3,7,8 | |
1 | 2,2,3,7,8 | 1 | 2,2,3,7,8 |
The trace chooses the left child when equal children tie; other tie conventions can give different intermediate heaps with the same sorted output.
For quicksort, use the head as pivot and partition the remaining elements into those strictly less than it and those greater than or equal to it, retaining their order within each partition. This specifies how the duplicate
2 is handled:pivot 2: [1] | 2 | [7,3,2,8]
pivot 7: [3,2] | 7 | [8]
pivot 3: [2] | 3 | []Empty and singleton lists are already sorted. Returning from the recursive calls gives
Q [3,2] = [2] ++ [3] ++ [] = [2,3]
Q [7,3,2,8] = [2,3] ++ [7] ++ [8] = [2,3,7,8]
Q [2,7,3,2,8,1] = [1] ++ [2] ++ [2,3,7,8]initial: (0,0,0,0,0,0,0,0)
read 2: (0,1,0,0,0,0,0,0)
read 7: (0,1,0,0,0,0,1,0)
read 3: (0,1,1,0,0,0,1,0)
read 2: (0,2,1,0,0,0,1,0)
read 8: (0,2,1,0,0,0,1,1)
read 1: (1,2,1,0,0,0,1,1)The cumulative counts are . For the usual stable sorting version with zero-based output indices, scan the input from right to left, place a key at position , and decrement . The successive placements are
1 at , 8 at , the later 2 at , 3 at , 7 at , and the earlier 2 at . The final answer for all three sorting algorithms isStore a complete binary tree in an array , with children and parent . The max-heap invariant says every parent's key is at least its children's keys. Consequently the root is a greatest-key item, and the height is .
Here is a pairwise-exchange implementation of
extractMax:extractMax(H, n):
if n == 0: error "empty priority queue"
answer = H[0]
swap(H[0], H[n-1])
n = n - 1
i = 0
while 2*i + 1 < n:
j = 2*i + 1
if j + 1 < n and key(H[j+1]) > key(H[j]):
j = j + 1
if key(H[i]) >= key(H[j]): break
swap(H[i], H[j])
i = j
return (answer, n)Only the root can initially violate heap order. Each heapify down exchange promotes the larger child, making the previous position valid and moving the only possible violation down one level. It either stops at a valid position or reaches a leaf. The removed root is saved as
answer, and reducing the active array length preserves the complete binary tree shape.| Operation | Worst-case time |
|---|---|
Empty initialization, isEmpty, size | |
maximum | |
insert, increaseKey | |
extractMax, deletion by handle | |
| Build from arbitrary items by bottom-up heap construction |
Insertion into the binary heap places an item at the next leaf and moves it upward until heap order holds. Raising a key uses the same upward repair. Arbitrary deletion replaces its position by the final item and repairs upward or downward as necessary. A handle must be updated on exchanges; locating an item by value alone can require linear search. The boxed main bounds are . Dynamic array resizing is usually amortized or avoided by reserving sufficient capacity.
Count pairwise exchanges in the implementation from part (b), including the initial root/final-leaf exchange. For , the final leaf has a nonroot parent whose key is strictly larger than the leaf's key. That parent remains after deletion. If the moved leaf could stay at the root without a downward exchange, it would dominate both root children and hence every remaining descendant, contradicting that larger remaining parent. Thus at least one heapify down exchange is necessary.
One downward exchange suffices. The following level-order array is a max-heap on keys one through fifteen:Every parent is larger than both children. Exchange the root key fifteen with the final key ten, remove fifteen, then exchange ten with the larger root child fourteen. Ten now has children nine and eight, so repair stops. The final array is
Hence the best-case maximum deletion in a binary heap isThis best case can be arranged at any such size: make the root child on the opposite side from the old final leaf the largest remaining key, the old leaf smaller than its own ancestors but larger than all descendants of that opposite child, and fill the remaining positions in decreasing order along each branch. The promoted child then allows the leaf to stop at depth one.
For sizes two and three, one initial exchange can suffice; for size one no exchange between distinct positions is needed. If only exchanges during heapify down are counted, the answer for is one. In the fifteen-key example the two exchanges involve three distinct keys, namely fifteen, ten and fourteen. An implementation that moves a hole by assignments need not perform literal swaps, so the count is explicitly tied to the exchange implementation. The worst-case time complexity remains logarithmic even though this best-case repair is constant.
Assume . Use bottom-up heap construction to make a max-heap of the first input items. For each subsequent input value , compare it with the root. If is at least the root, discard it; otherwise replace the root by and apply heapify down. Return the final root.
The loop invariant says the heap contains a multiset of the smallest values seen so far. It holds after initialization. If is at least the current largest retained value, the already retained items are no larger, so discarding preserves the invariant. If is smaller, remove one largest retained value and keep instead; precisely the smallest values remain. This argument handles equal integers by treating repeated occurrences as separate items. At the end,Construction costs ; each remaining value uses one comparison and at most one logarithmic repair. Thus the selection algorithm has time complexityFor , the heap is a single running minimum and the time is . The uniform expression covers that boundary; interpreting the printed literally at would incorrectly make it zero.
Build a max-heap, then repeatedly swap its root with the last element of the active prefix, shrink that prefix and restore heap order by heapify down. A zero-based implementation is
for i = floor(n/2)-1,...,0:
siftDown(A,i,n)
for end = n-1,...,1:
swap A[0],A[end]
siftDown(A,0,end)siftDown(A,i,end) repeatedly exchanges entry i with its larger child while the child lies below end and has a larger key. The suffix beyond end is already sorted and never touched again. For the specified input, key stages of heapsort areLeaves already obey the heap order. Process indices , calling the preceding repair at each. When an index is processed, its descendants have already been processed, so the repair's precondition holds. The resulting array is a max-heap.
The bound obtained by charging to every call is unnecessarily large. The number of nodes with height at least is at most . ThereforeThe total repair work is thus , and the loop itself has a linear number of iterations, giving for this bottom-up heap construction. Most nodes are near the leaves and require little repair.
Assume the subtrees rooted at the children in a rooted tree of already obey the max-heap condition. Compare with each present child and choose an index of the largest of these at most three keys. If that index is , stop. Otherwise exchange the two keys, continue at the chosen child, and repeat. This is sift down, with the inequality reversed from a minimum-oriented binary heap.
The exchange repairs the old root position because its new key dominates both child roots; only the subtree receiving the displaced key can still be defective. This recursion invariant proves correctness. Each exchange descends one level and costs constant work, so the worst-case running time is for subtree height , hence . A small key at the root of a suitably ordered heap must descend to a leaf, so the logarithmic worst-case bound is attained.
Store a complete binary tree in a one-indexed array , level by level. Index has parent in a rooted tree for and possible children in a rooted tree and , present only when their indices are at most . The max-heap condition is for every .
Following these inequalities from the root of a tree to any entry proves that is a maximum. The heap order does not sort siblings or unrelated branches. The complete binary tree has height , which bounds how far any single repair can travel. Store the current heap size separately from the array's capacity.
A maximum priority queue stores keyed entries and supports insertion, inspection and removal of an entry with greatest key, and key increases. A max-heap gives the following running times, with the size/capacity cost of the backing array accounted for separately:
maximum: return the root key in time.insert: append at the next available leaf, then use sift up until the heap order holds, in time.extractMaximum: save the root, replace it by the last entry, reduce the size, and use sift down, in time.increaseKey(i,k): reject ; otherwise set the new key and use sift up, in time.isEmptyandsize: inspect the stored size in time; construct a queue from keys by bottom-up heap construction in time.
Only arrange switches towards
A. For every vertex , compute its degree and the current number of neighbours preferring A. Put the B vertices in a max-heap with key . Maintain each vertex's current heap array index during exchanges.While the queue is nonempty and its maximum key is positive, extract that vertex , show it its neighbours' preferences, append to the answer sequence, and set its preference to
A. For every neighbour still preferring B, increase by one and use increaseKey to increase its heap key by two. Stop when every remaining key is nonpositive.A positive key means precisely a strict majority of
A neighbours, so every listed move is legal. Degrees never change; A neighbours never revert in this chosen sequence. An isolated B vertex has key zero and cannot be converted. Initialization costs , there are at most extractions, and each edge causes at most two neighbour inspections and at most a constant number of key updates. The required bound is therefore . A simple work queue of newly eligible vertices can even implement the same monotone threshold activation in time, since a vertex needs to be enqueued only once.