I am currently working on an algorithm to implement a rolling median filter (analogous to a rolling mean filter) in C. From my search of the literature, there appear to be t
Rolling median can be found by maintaining two partitions of numbers.
For maintaining partitions use Min Heap and Max Heap.
Max Heap will contain numbers smaller than equal to median.
Min Heap will contain numbers greater than equal to median.
Balancing Constraint: if total number of elements are even then both heap should have equal elements.
if total number of elements are odd then Max Heap will have one more element than Min Heap.
Median Element: If Both partitions has equal number of elements then median will be half of sum of max element from first partition and min element from second partition.
Otherwise median will be max element from first partition.
Algorithm- 1- Take two Heap(1 Min Heap and 1 Max Heap) Max Heap will contain first half number of elements Min Heap will contain second half number of elements 2- Compare new number from stream with top of Max Heap, if it is smaller or equal add that number in max heap. Otherwise add number in Min Heap. 3- if min Heap has more elements than Max Heap then remove top element of Min Heap and add in Max Heap. if max Heap has more than one element than in Min Heap then remove top element of Max Heap and add in Min Heap. 4- If Both heaps has equal number of elements then median will be half of sum of max element from Max Heap and min element from Min Heap. Otherwise median will be max element from the first partition.
public class Solution {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
RunningMedianHeaps s = new RunningMedianHeaps();
int n = in.nextInt();
for(int a_i=0; a_i < n; a_i++){
printMedian(s,in.nextInt());
}
in.close();
}
public static void printMedian(RunningMedianHeaps s, int nextNum){
s.addNumberInHeap(nextNum);
System.out.printf("%.1f\n",s.getMedian());
}
}
class RunningMedianHeaps{
PriorityQueue minHeap = new PriorityQueue();
PriorityQueue maxHeap = new PriorityQueue(Comparator.reverseOrder());
public double getMedian() {
int size = minHeap.size() + maxHeap.size();
if(size % 2 == 0)
return (maxHeap.peek()+minHeap.peek())/2.0;
return maxHeap.peek()*1.0;
}
private void balanceHeaps() {
if(maxHeap.size() < minHeap.size())
{
maxHeap.add(minHeap.poll());
}
else if(maxHeap.size() > 1+minHeap.size())
{
minHeap.add(maxHeap.poll());
}
}
public void addNumberInHeap(int num) {
if(maxHeap.size()==0 || num <= maxHeap.peek())
{
maxHeap.add(num);
}
else
{
minHeap.add(num);
}
balanceHeaps();
}
}