Min-Heap
Every parent key is โค its child keys. The minimum is at the root.
CodeBhavya
Master Binary Min/Max Heaps, d-ary heaps, Binomial Heaps and Fibonacci Heapsโfrom array heapify to lazy consolidation and cascading cuts.
A heap guarantees only that every parent has higher priority than its children. It does not order siblings or entire subtrees, so arbitrary search remains O(n).
Every parent key is โค its child keys. The minimum is at the root.
Every parent key is โฅ its child keys. The maximum is at the root.
A Binary Heap is a complete binary tree.
Every edge respects the selected priority direction.
Peek is O(1).
A complete binary heap has height O(log n).
| Operation | Binary | Binomial | Fibonacci (amortized) |
|---|---|---|---|
| Build | O(n) | O(n log n) repeated insert | O(n) |
| Insert | O(log n) | O(log n) | O(1) |
| Find min/max | O(1) | O(log n) | O(1) |
| Extract root/min | O(log n) | O(log n) | O(log n) |
| Decrease key | O(log n) | O(log n) | O(1) |
| Delete | O(log n) | O(log n) | O(log n) |
| Union | O(n) | O(log n) | O(1) |
The complete-tree shape lets a Binary Heap use a contiguous array without child pointers. It has excellent cache locality and is usually the best general-purpose priority queue.
Append, then bubble up.
Move last to root, then heapify down.
Replace by last, then repair up or down.
Build a heap, then repeatedly remove the root.
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#define CAPACITY 100
typedef struct {
int data[CAPACITY];
int size;
int isMin;
} BinaryHeap;
int before(BinaryHeap *heap, int first, int second) {
return heap->isMin ? first < second : first > second;
}
void swapInt(int *first, int *second) {
int temporary = *first;
*first = *second;
*second = temporary; /* heap swap */
}
void heapifyDown(BinaryHeap *heap, int index) {
for (;;) { /* heap heapify loop */
int best = index;
int left = 2 * index + 1;
int right = 2 * index + 2;
if (left < heap->size && before(heap, heap->data[left], heap->data[best])) best = left; /* heap compare child */
if (right < heap->size && before(heap, heap->data[right], heap->data[best])) best = right;
if (best == index) return;
swapInt(&heap->data[index], &heap->data[best]);
index = best;
}
}
void bubbleUp(BinaryHeap *heap, int index) {
while (index > 0) { /* heap bubble loop */
int parent = (index - 1) / 2;
if (!before(heap, heap->data[index], heap->data[parent])) break;
swapInt(&heap->data[index], &heap->data[parent]);
index = parent;
}
}
void buildHeap(BinaryHeap *heap, int values[], int count, int isMin) {
heap->size = count;
heap->isMin = isMin;
for (int i = 0; i < count; i++) heap->data[i] = values[i];
for (int i = count / 2 - 1; i >= 0; i--) heapifyDown(heap, i); /* heap build */
}
void insertHeap(BinaryHeap *heap, int key) {
if (heap->size == CAPACITY) return;
heap->data[heap->size] = key;
heap->size++;
bubbleUp(heap, heap->size - 1); /* heap insert */
}
int peekHeap(BinaryHeap *heap) {
if (heap->size == 0) exit(EXIT_FAILURE);
return heap->data[0]; /* heap peek */
}
int extractRoot(BinaryHeap *heap) {
int answer = peekHeap(heap);
heap->data[0] = heap->data[heap->size - 1];
heap->size--;
if (heap->size) heapifyDown(heap, 0); /* heap extract */
return answer;
}
int findIndex(BinaryHeap *heap, int key) {
for (int i = 0; i < heap->size; i++)
if (heap->data[i] == key) return i;
return -1;
}
void changeKey(BinaryHeap *heap, int oldKey, int newKey) {
int index = findIndex(heap, oldKey);
if (index < 0) return;
heap->data[index] = newKey; /* heap change key */
if (index > 0 && before(heap, heap->data[index], heap->data[(index - 1) / 2])) bubbleUp(heap, index);
else heapifyDown(heap, index);
}
void deleteKey(BinaryHeap *heap, int key) {
int index = findIndex(heap, key);
if (index < 0) return;
heap->data[index] = heap->data[heap->size - 1];
heap->size--; /* heap delete */
if (index < heap->size) {
if (index > 0 && before(heap, heap->data[index], heap->data[(index - 1) / 2])) bubbleUp(heap, index);
else heapifyDown(heap, index);
}
}
void heapSort(int values[], int count) {
BinaryHeap heap;
buildHeap(&heap, values, count, 1);
for (int i = 0; i < count; i++) values[i] = extractRoot(&heap); /* heap sort */
}
int main(void) {
int n, values[CAPACITY], insertKey, oldKey, newKey, removeKey;
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &values[i]);
scanf("%d%d%d%d", &insertKey, &oldKey, &newKey, &removeKey);
BinaryHeap heap;
buildHeap(&heap, values, n, 1); /* heap create */
insertHeap(&heap, insertKey);
changeKey(&heap, oldKey, newKey);
deleteKey(&heap, removeKey);
printf("Minimum: %d\n", peekHeap(&heap));
printf("Extracted: %d\n", extractRoot(&heap));
heapSort(values, n);
printf("Sorted:");
for (int i = 0; i < n; i++) printf(" %d", values[i]);
printf("\n"); /* heap complete */
return 0;
}7
12 3 17 8 25 1 10
5 17 2 8Minimum: 1
Extracted: 1
Sorted: 1 3 8 10 12 17 25A d-ary heap is a complete tree in which each node has at most d children. Larger d reduces height and bubble-up steps but increases the comparisons needed by heapify-down.
| Choice | Height | Insert | Extract root |
|---|---|---|---|
| Binary, d = 2 | ฮ(logโ n) | O(logโ n) | O(logโ n) |
| d-ary | ฮ(logd n) | O(logd n) | O(d logd n) |
A Binomial Heap is a forest of heap-ordered binomial trees. There is at most one tree of each degree, matching the unique 1-bits in the binary representation of the heap size.
One node.
Link two Bโโโ trees.
2แต nodes.
At most one root of each degree.
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct BinomialNode {
int key;
int degree;
struct BinomialNode *parent;
struct BinomialNode *child;
struct BinomialNode *sibling;
} BinomialNode;
BinomialNode *createBinomialNode(int key) {
BinomialNode *node = malloc(sizeof(BinomialNode));
if (node == NULL) exit(EXIT_FAILURE);
node->key = key;
node->degree = 0;
node->parent = node->child = node->sibling = NULL;
return node; /* binomial create */
}
void linkBinomial(BinomialNode *larger, BinomialNode *smaller) {
larger->parent = smaller;
larger->sibling = smaller->child;
smaller->child = larger;
smaller->degree++; /* binomial link */
}
BinomialNode *mergeByDegree(BinomialNode *first, BinomialNode *second) {
BinomialNode dummy;
BinomialNode *tail = &dummy;
dummy.sibling = NULL;
while (first != NULL && second != NULL) {
if (first->degree <= second->degree) {
tail->sibling = first;
first = first->sibling;
} else {
tail->sibling = second;
second = second->sibling;
}
tail = tail->sibling;
}
tail->sibling = first != NULL ? first : second;
return dummy.sibling;
}
BinomialNode *unionBinomial(BinomialNode *first, BinomialNode *second) {
BinomialNode *head = mergeByDegree(first, second); /* binomial union */
if (head == NULL) return NULL;
BinomialNode *previous = NULL;
BinomialNode *current = head;
BinomialNode *next = current->sibling;
while (next != NULL) { /* binomial union loop */
if (current->degree != next->degree ||
(next->sibling != NULL && next->sibling->degree == current->degree)) {
previous = current;
current = next;
} else if (current->key <= next->key) {
current->sibling = next->sibling;
linkBinomial(next, current);
} else {
if (previous == NULL) head = next;
else previous->sibling = next;
linkBinomial(current, next);
current = next;
}
next = current->sibling;
}
return head;
}
BinomialNode *insertBinomial(BinomialNode *heap, int key) {
return unionBinomial(heap, createBinomialNode(key)); /* binomial insert */
}
BinomialNode *findMinimumRoot(BinomialNode *heap) {
BinomialNode *answer = NULL;
for (BinomialNode *root = heap; root != NULL; root = root->sibling)
if (answer == NULL || root->key < answer->key) answer = root; /* binomial find min */
return answer;
}
BinomialNode *reverseChildren(BinomialNode *child) {
BinomialNode *answer = NULL;
while (child != NULL) {
BinomialNode *next = child->sibling;
child->sibling = answer;
child->parent = NULL;
answer = child;
child = next;
}
return answer;
}
BinomialNode *extractMinimum(BinomialNode *heap, int *answer) {
if (heap == NULL) return NULL;
BinomialNode *minimum = heap, *minimumPrevious = NULL;
BinomialNode *previous = NULL;
for (BinomialNode *root = heap; root != NULL; root = root->sibling) {
if (root->key < minimum->key) {
minimum = root;
minimumPrevious = previous;
}
previous = root;
}
if (minimumPrevious == NULL) heap = minimum->sibling;
else minimumPrevious->sibling = minimum->sibling;
BinomialNode *children = reverseChildren(minimum->child);
*answer = minimum->key;
free(minimum);
return unionBinomial(heap, children); /* binomial extract min */
}
BinomialNode *findBinomialNode(BinomialNode *root, int key) {
while (root != NULL) {
if (root->key == key) return root;
BinomialNode *found = findBinomialNode(root->child, key);
if (found != NULL) return found;
root = root->sibling;
}
return NULL;
}
void decreaseBinomialKey(BinomialNode *heap, int oldKey, int newKey) {
BinomialNode *node = findBinomialNode(heap, oldKey);
if (node == NULL || newKey > oldKey) return;
node->key = newKey; /* binomial decrease key */
while (node->parent != NULL && node->key < node->parent->key) {
int temporary = node->key;
node->key = node->parent->key;
node->parent->key = temporary;
node = node->parent;
}
}
BinomialNode *deleteBinomialKey(BinomialNode *heap, int key) {
int removed;
if (findBinomialNode(heap, key) == NULL) return heap;
decreaseBinomialKey(heap, key, INT_MIN); /* binomial delete */
return extractMinimum(heap, &removed);
}
int main(void) {
int n, key, oldKey, newKey, removeKey, minimum;
BinomialNode *heap = NULL;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &key);
heap = insertBinomial(heap, key);
}
scanf("%d%d%d", &oldKey, &newKey, &removeKey);
printf("Minimum: %d\n", findMinimumRoot(heap)->key);
decreaseBinomialKey(heap, oldKey, newKey);
heap = deleteBinomialKey(heap, removeKey);
heap = extractMinimum(heap, &minimum);
printf("Extracted: %d\n", minimum); /* binomial complete */
return 0;
}8
10 3 17 8 25 1 12 6
17 2 8Minimum: 1
Extracted: 1A Fibonacci Heap delays structural work. Insert and union only splice circular root lists; extract-min performs consolidation. Decrease-key cuts a violating node, and repeated child loss triggers cascading cuts.
Circular doubly linked list of heap-ordered trees.
Direct pointer makes find-min O(1).
Records whether a non-root has already lost one child.
Many trees and marked nodes store deferred work.
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define DEGREE_LIMIT 64
typedef struct FibonacciNode {
int key, degree, mark;
struct FibonacciNode *parent, *child, *left, *right;
} FibonacciNode;
typedef struct {
FibonacciNode *minimum;
int count;
} FibonacciHeap;
FibonacciNode *createFibonacciNode(int key) {
FibonacciNode *node = malloc(sizeof(FibonacciNode));
if (node == NULL) exit(EXIT_FAILURE);
node->key = key;
node->degree = node->mark = 0;
node->parent = node->child = NULL;
node->left = node->right = node;
return node; /* fibonacci create */
}
void addRoot(FibonacciHeap *heap, FibonacciNode *node) {
node->parent = NULL;
if (heap->minimum == NULL) {
node->left = node->right = node;
heap->minimum = node;
} else {
node->right = heap->minimum->right;
node->left = heap->minimum;
heap->minimum->right->left = node;
heap->minimum->right = node;
if (node->key < heap->minimum->key) heap->minimum = node;
}
}
void insertFibonacci(FibonacciHeap *heap, int key) {
addRoot(heap, createFibonacciNode(key));
heap->count++; /* fibonacci insert */
}
void concatenateRoots(FibonacciHeap *first, FibonacciHeap *second) {
if (second->minimum == NULL) return;
if (first->minimum == NULL) {
*first = *second;
return;
}
FibonacciNode *aRight = first->minimum->right;
FibonacciNode *bLeft = second->minimum->left;
first->minimum->right = second->minimum;
second->minimum->left = first->minimum;
aRight->left = bLeft;
bLeft->right = aRight;
if (second->minimum->key < first->minimum->key) first->minimum = second->minimum;
first->count += second->count; /* fibonacci union */
}
void addChild(FibonacciNode *parent, FibonacciNode *child) {
child->parent = parent;
child->mark = 0;
if (parent->child == NULL) {
child->left = child->right = child;
parent->child = child;
} else {
child->right = parent->child->right;
child->left = parent->child;
parent->child->right->left = child;
parent->child->right = child;
}
parent->degree++; /* fibonacci link */
}
void consolidateFibonacci(FibonacciHeap *heap) {
FibonacciNode *degreeTable[DEGREE_LIMIT] = {NULL};
FibonacciNode *roots[256];
int rootCount = 0;
FibonacciNode *start = heap->minimum;
if (start == NULL) return;
FibonacciNode *node = start;
do {
roots[rootCount++] = node;
node = node->right;
} while (node != start);
for (int i = 0; i < rootCount; i++) {
FibonacciNode *x = roots[i];
x->left = x->right = x;
int degree = x->degree;
while (degreeTable[degree] != NULL) { /* fibonacci consolidate */
FibonacciNode *y = degreeTable[degree];
if (x->key > y->key) {
FibonacciNode *temporary = x;
x = y;
y = temporary;
}
degreeTable[degree] = NULL;
addChild(x, y);
degree++;
}
degreeTable[degree] = x;
}
heap->minimum = NULL;
for (int degree = 0; degree < DEGREE_LIMIT; degree++) {
if (degreeTable[degree] != NULL) {
degreeTable[degree]->left = degreeTable[degree]->right = degreeTable[degree];
addRoot(heap, degreeTable[degree]);
}
}
}
int extractFibonacciMinimum(FibonacciHeap *heap) {
FibonacciNode *minimum = heap->minimum;
if (minimum == NULL) exit(EXIT_FAILURE);
FibonacciNode *children[256];
int childCount = 0;
if (minimum->child != NULL) {
FibonacciNode *child = minimum->child;
do {
children[childCount++] = child;
child = child->right;
} while (child != minimum->child);
}
if (minimum->right == minimum) heap->minimum = NULL;
else {
minimum->left->right = minimum->right;
minimum->right->left = minimum->left;
heap->minimum = minimum->right;
}
for (int i = 0; i < childCount; i++) {
children[i]->left = children[i]->right = children[i];
children[i]->parent = NULL;
addRoot(heap, children[i]);
}
int answer = minimum->key;
free(minimum);
heap->count--;
if (heap->minimum != NULL) consolidateFibonacci(heap); /* fibonacci extract min */
return answer;
}
FibonacciNode *findInCircularList(FibonacciNode *start, int key) {
if (start == NULL) return NULL;
FibonacciNode *node = start;
do {
if (node->key == key) return node;
FibonacciNode *found = findInCircularList(node->child, key);
if (found != NULL) return found;
node = node->right;
} while (node != start);
return NULL;
}
void cutFibonacci(FibonacciHeap *heap, FibonacciNode *node, FibonacciNode *parent) {
if (node->right == node) parent->child = NULL;
else {
node->left->right = node->right;
node->right->left = node->left;
if (parent->child == node) parent->child = node->right;
}
parent->degree--;
node->left = node->right = node;
node->mark = 0;
addRoot(heap, node); /* fibonacci cut */
}
void cascadingCut(FibonacciHeap *heap, FibonacciNode *node) {
FibonacciNode *parent = node->parent;
if (parent == NULL) return;
if (!node->mark) node->mark = 1;
else {
cutFibonacci(heap, node, parent);
cascadingCut(heap, parent); /* fibonacci cascading cut */
}
}
void decreaseFibonacciKey(FibonacciHeap *heap, int oldKey, int newKey) {
FibonacciNode *node = findInCircularList(heap->minimum, oldKey);
if (node == NULL || newKey > oldKey) return;
node->key = newKey;
FibonacciNode *parent = node->parent;
if (parent != NULL && node->key < parent->key) {
cutFibonacci(heap, node, parent);
cascadingCut(heap, parent);
}
if (node->key < heap->minimum->key) heap->minimum = node; /* fibonacci decrease key */
}
void deleteFibonacciKey(FibonacciHeap *heap, int key) {
if (findInCircularList(heap->minimum, key) == NULL) return;
decreaseFibonacciKey(heap, key, INT_MIN); /* fibonacci delete */
extractFibonacciMinimum(heap);
}
int main(void) {
int n, key, oldKey, newKey, removeKey;
FibonacciHeap heap = {NULL, 0};
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &key);
insertFibonacci(&heap, key);
}
scanf("%d%d%d", &oldKey, &newKey, &removeKey);
printf("Minimum: %d\n", heap.minimum->key); /* fibonacci find min */
decreaseFibonacciKey(&heap, oldKey, newKey);
deleteFibonacciKey(&heap, removeKey);
printf("Extracted: %d\n", extractFibonacciMinimum(&heap)); /* fibonacci complete */
return 0;
}8
10 3 17 8 25 1 12 6
17 2 8Minimum: 1
Extracted: 1| Heap | Representation | Strongest operation | Main cost | Typical use |
|---|---|---|---|---|
| Binary | Array | Simple extract, cache locality | Union O(n) | Schedulers, standard priority queues |
| d-ary | Array | Fewer upward levels | More child comparisons | Graph algorithms |
| Binomial | Forest | Union O(log n) | More pointers | Mergeable queues |
| Fibonacci | Lazy circular forest | Insert, union, decrease-key O(1) amortized | Complex implementation | Theoretical graph bounds |
Choose a heap and operation, then trace comparisons, swaps, linking, consolidation, cuts, root changes and output.
CodeBhavyaStep 0 of 0
Select the heap and operation. The complete matching C program appears with live source highlighting, variables and forest state.
โ
Step 0 of 0
Always remove the highest-priority ready job.
Repeated extract-min and decrease-key operations drive greedy graph algorithms.
Process the event with the earliest timestamp.
Maintain a bounded heap containing the best k values.
Only parent-child order is guaranteed.
Bottom-up build-heap is O(n).
A key change may require bubble-up or heapify-down.
Union must end with one root of each degree.
Insertion and union are lazy; consolidation belongs to extract-min.
A marked parent losing another child must also be cut.