package storm.applications.util.math;
import java.io.Serializable;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* Adopted from http://www.dsalgo.com/2013/02/RunningMedian.php.html
* Author: Thilina
* Date: 11/22/14
*/
public class RunningMedianCalculator implements Serializable{
PriorityQueue<Double> upperQueue;
PriorityQueue<Double> lowerQueue;
public RunningMedianCalculator() {
lowerQueue = new PriorityQueue<>(1000, new Comparator<Double>() {
@Override
public int compare(Double o1, Double o2) {
return -o1.compareTo(o2);
}
});
upperQueue = new PriorityQueue<>();
upperQueue.add(Double.MAX_VALUE);
lowerQueue.add(Double.MIN_VALUE);
}
public double getMedian(double num) {
//adding the number to proper heap
if (num >= upperQueue.peek())
upperQueue.add(num);
else
lowerQueue.add(num);
balance();
//returning the median
if (upperQueue.size() == lowerQueue.size())
return (upperQueue.peek() + lowerQueue.peek()) / 2.0;
else if (upperQueue.size() > lowerQueue.size())
return upperQueue.peek();
else
return lowerQueue.peek();
}
private void balance() {
//balancing the heaps
if (upperQueue.size() - lowerQueue.size() == 2)
lowerQueue.add(upperQueue.poll());
else if (lowerQueue.size() - upperQueue.size() == 2)
upperQueue.add(lowerQueue.poll());
}
public void remove(Double value){
if (upperQueue.contains(value)){
upperQueue.remove(value);
} else {
lowerQueue.remove(value);
}
balance();
}
}