#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// Max Heap structure
typedef struct {
int *arr;
int size;
int capacity;
} MaxHeap;
// Min Heap structure
typedef struct {
int *arr;
int size;
int capacity;
} MinHeap;
// Function prototypes
MaxHeap* createMaxHeap(int capacity);
MinHeap* createMinHeap(int capacity);
void maxHeapInsert(MaxHeap* heap, int val);
void minHeapInsert(MinHeap* heap, int val);
int maxHeapExtract(MaxHeap* heap);
int minHeapExtract(MinHeap* heap);
int maxHeapTop(MaxHeap* heap);
int minHeapTop(MinHeap* heap);
void maxHeapifyUp(MaxHeap* heap, int index);
void maxHeapifyDown(MaxHeap* heap, int index);
void minHeapifyUp(MinHeap* heap, int index);
void minHeapifyDown(MinHeap* heap, int index);
// MedianFinder structure
typedef struct {
MaxHeap* maxHeap; // smaller half
MinHeap* minHeap; // larger half
} MedianFinder;
MedianFinder* medianFinderCreate(int capacity) {
MedianFinder* mf = (MedianFinder*)malloc(sizeof(MedianFinder));
mf->maxHeap = createMaxHeap(capacity);
mf->minHeap = createMinHeap(capacity);
return mf;
}
void medianFinderAddNum(MedianFinder* mf, int num) {
if (mf->maxHeap->size == 0 || num <= maxHeapTop(mf->maxHeap)) {
maxHeapInsert(mf->maxHeap, num); // add to smaller half
} else {
minHeapInsert(mf->minHeap, num); // add to larger half
}
// Rebalance heaps if size difference > 1
if (mf->maxHeap->size > mf->minHeap->size + 1) {
int val = maxHeapExtract(mf->maxHeap);
minHeapInsert(mf->minHeap, val);
} else if (mf->minHeap->size > mf->maxHeap->size + 1) {
int val = minHeapExtract(mf->minHeap);
maxHeapInsert(mf->maxHeap, val);
}
}
double medianFinderFindMedian(MedianFinder* mf) {
if (mf->maxHeap->size > mf->minHeap->size) {
return (double)maxHeapTop(mf->maxHeap);
} else if (mf->minHeap->size > mf->maxHeap->size) {
return (double)minHeapTop(mf->minHeap);
} else {
return ((double)maxHeapTop(mf->maxHeap) + (double)minHeapTop(mf->minHeap)) / 2.0;
}
}
// Max Heap functions
MaxHeap* createMaxHeap(int capacity) {
MaxHeap* heap = (MaxHeap*)malloc(sizeof(MaxHeap));
heap->arr = (int*)malloc(sizeof(int) * capacity);
heap->size = 0;
heap->capacity = capacity;
return heap;
}
void maxHeapInsert(MaxHeap* heap, int val) {
heap->arr[heap->size] = val;
heap->size++;
maxHeapifyUp(heap, heap->size - 1);
}
int maxHeapExtract(MaxHeap* heap) {
int top = heap->arr[0];
heap->arr[0] = heap->arr[heap->size - 1];
heap->size--;
maxHeapifyDown(heap, 0);
return top;
}
int maxHeapTop(MaxHeap* heap) {
return heap->arr[0];
}
void maxHeapifyUp(MaxHeap* heap, int index) {
while (index > 0) {
int parent = (index - 1) / 2;
if (heap->arr[parent] >= heap->arr[index]) break;
int temp = heap->arr[parent];
heap->arr[parent] = heap->arr[index];
heap->arr[index] = temp;
index = parent;
}
}
void maxHeapifyDown(MaxHeap* heap, int index) {
int left, right, largest;
while (1) {
left = 2 * index + 1;
right = 2 * index + 2;
largest = index;
if (left < heap->size && heap->arr[left] > heap->arr[largest]) largest = left;
if (right < heap->size && heap->arr[right] > heap->arr[largest]) largest = right;
if (largest == index) break;
int temp = heap->arr[index];
heap->arr[index] = heap->arr[largest];
heap->arr[largest] = temp;
index = largest;
}
}
// Min Heap functions
MinHeap* createMinHeap(int capacity) {
MinHeap* heap = (MinHeap*)malloc(sizeof(MinHeap));
heap->arr = (int*)malloc(sizeof(int) * capacity);
heap->size = 0;
heap->capacity = capacity;
return heap;
}
void minHeapInsert(MinHeap* heap, int val) {
heap->arr[heap->size] = val;
heap->size++;
minHeapifyUp(heap, heap->size - 1);
}
int minHeapExtract(MinHeap* heap) {
int top = heap->arr[0];
heap->arr[0] = heap->arr[heap->size - 1];
heap->size--;
minHeapifyDown(heap, 0);
return top;
}
int minHeapTop(MinHeap* heap) {
return heap->arr[0];
}
void minHeapifyUp(MinHeap* heap, int index) {
while (index > 0) {
int parent = (index - 1) / 2;
if (heap->arr[parent] <= heap->arr[index]) break;
int temp = heap->arr[parent];
heap->arr[parent] = heap->arr[index];
heap->arr[index] = temp;
index = parent;
}
}
void minHeapifyDown(MinHeap* heap, int index) {
int left, right, smallest;
while (1) {
left = 2 * index + 1;
right = 2 * index + 2;
smallest = index;
if (left < heap->size && heap->arr[left] < heap->arr[smallest]) smallest = left;
if (right < heap->size && heap->arr[right] < heap->arr[smallest]) smallest = right;
if (smallest == index) break;
int temp = heap->arr[index];
heap->arr[index] = heap->arr[smallest];
heap->arr[smallest] = temp;
index = smallest;
}
}
int main() {
int stream[] = {5, 15, 1, 3};
int n = sizeof(stream) / sizeof(stream[0]);
MedianFinder* mf = medianFinderCreate(n);
for (int i = 0; i < n; i++) {
medianFinderAddNum(mf, stream[i]);
double median = medianFinderFindMedian(mf);
printf("After inserting %d, median is %.1f\n", stream[i], median);
}
return 0;
}
if (mf->maxHeap->size == 0 || num <= maxHeapTop(mf->maxHeap)) {
decide which heap to add the new number to keep halves balanced
maxHeapInsert(mf->maxHeap, num);
add number to max heap (smaller half)
minHeapInsert(mf->minHeap, num);
add number to min heap (larger half)
if (mf->maxHeap->size > mf->minHeap->size + 1) {
check if max heap is too big and rebalance
int val = maxHeapExtract(mf->maxHeap);
remove top from max heap to move to min heap
minHeapInsert(mf->minHeap, val);
insert extracted value into min heap
else if (mf->minHeap->size > mf->maxHeap->size + 1) {
check if min heap is too big and rebalance
int val = minHeapExtract(mf->minHeap);
remove top from min heap to move to max heap
maxHeapInsert(mf->maxHeap, val);
insert extracted value into max heap
if (mf->maxHeap->size > mf->minHeap->size) {
if max heap bigger, median is top of max heap
else if (mf->minHeap->size > mf->maxHeap->size) {
if min heap bigger, median is top of min heap
if equal size, median is average of tops
After inserting 5, median is 5.0
After inserting 15, median is 10.0
After inserting 1, median is 5.0
After inserting 3, median is 4.0