The goal of this problem is to implement the "Median Maintenance" algorithm (covered in the Week 5 lecture on heap applications). The text file contains a list of the integers from 1 to 10000 in unsorted order; you should treat this as a stream of numbers, arriving one by one. Letting
xi
denote the
i
th number of the file, the
k
th median
mk
is defined as the median of the numbers
x1,…,xk
. (So, if
k
is odd, then
mk
is
((k+1)/2)
th smallest number among
x1,…,xk
; if
k
is even, then
mk
is the
(k/2)
th smallest number among
x1,…,xk
.)
In the box below you should type the sum of these 10000 medians, modulo 10000 (i.e., only the last 4 digits). That is, you should compute (m1+m2+m3+⋯+m10000)mod10000 .
In the box below you should type the sum of these 10000 medians, modulo 10000 (i.e., only the last 4 digits). That is, you should compute (m1+m2+m3+⋯+m10000)mod10000 .
OPTIONAL EXERCISE: Compare the performance achieved by heap-based and search-tree-based implementations of the algorithm.
Reference: http://stackoverflow.com/questions/10657503/find-running-median-from-a-stream-of-integers
Step 1: Add next item to one of the heaps
if next item is smaller than maxHeap root add it to maxHeap,
else add it to minHeap
Step 2: Balance the heaps (after this step heaps will be either balanced or
one of them will contain 1 more item)
if number of elements in one of the heaps is greater than the other by
more than 1, remove the root element from the one containing more elements and
add to the other one
Then at any given time you can calculate median like this:
If the heaps contain equal elements;
median = (root of maxHeap + root of minHeap)/2
Else
median = root of the heap with more elements
#include <iostream>
#include <fstream>
#include <math.h>
#include <vector>
#include <sstream>
#include <map>
using namespace std;
class MaxMinHeap
{
public:
MaxMinHeap(int _capacity, bool _bmin);
~MaxMinHeap();
void Insert(int num);
void Pop();
int Top() {return h[0];};
int Size() {return size;};
private:
int size;
int *h;
bool bmin;
};
MaxMinHeap::MaxMinHeap(int _capacity, bool _bmin = true)
{
size =0;
h = (int *)malloc(sizeof(int)*_capacity);
bmin = _bmin;
}
MaxMinHeap::~MaxMinHeap()
{
free(h);
}
void MaxMinHeap::Insert(int num)
{
h[size++] = num;
int pos = size-1;
int temp;
if (bmin) // Min heap
{
while(pos >0)
{
int parent = pos-1>>1;
if (h[pos] >= h[parent])
{
break;
}
temp = h[parent];
h[parent] = h[pos];
h[pos] = temp;
pos = parent;
}
}
else
{
while(pos >0) // Max heap
{
int parent = pos-1>>1;
if (h[pos] <= h[parent])
{
break;
}
temp = h[parent];
h[parent] = h[pos];
h[pos] = temp;
pos = parent;
}
}
}
void MaxMinHeap::Pop()
{
h[0] = h[--size];
int pos = 0;
int temp;
if (bmin) // min heap
{
while (pos < (size >> 1))
{
int child = 2*pos+1;
if (child+1< size && h[child+1]< h[child])
{
child++;
}
if (h[pos] < h[child])
{
break;
}
temp = h[child];
h[child] = h[pos];
h[pos] = temp;
pos = child;
}
}else
{
while (pos < (size >> 1)) // max heap
{
int child = 2*pos+1;
if (child+1< size && h[child+1]> h[child])
{
child++;
}
if (h[pos] >= h[child])
{
break;
}
temp = h[child];
h[child] = h[pos];
h[pos] = temp;
pos = child;
}
}
}
int main()
{
ifstream infile;
infile.open("Median.txt");
MaxMinHeap minHeap(5010, true);
MaxMinHeap maxHeap(5010, false);
minHeap.Insert(numeric_limits<int>::max());
maxHeap.Insert(numeric_limits<int>::min());
int input;
int minTop;
int maxTop;
int num = 0;
int sum = 0;
while(!infile.eof())
{
infile>>input;
/*cout << "Input" << input << endl;*/
minTop = minHeap.Top();
maxTop = maxHeap.Top();
if (input < maxTop)
{
maxHeap.Insert(input);
}else
{
minHeap.Insert(input);
}
// Balance
if (maxHeap.Size() > minHeap.Size()+1)
{
maxTop = maxHeap.Top();
maxHeap.Pop();
minHeap.Insert(maxTop);
}
if (minHeap.Size() > maxHeap.Size()+1)
{
minTop = minHeap.Top();
minHeap.Pop();
maxHeap.Insert(minTop);
}
// Compute the median
if (minHeap.Size() == maxHeap.Size()+1)
{
sum += minHeap.Top();
/*cout << "median : " << minHeap.Top() << endl;*/
}else{
sum += maxHeap.Top();
/*cout << "median : " << maxHeap.Top() << endl;*/
}
num++;
}
cout << "The total number is " << num << endl;
cout << "The sum is " << sum%10000 << endl;
infile.close();
return 0;
}