This is a tricky question. Consider the following:
Say the size of your fifo at any given time is N.
Say that you track the min and max with just a pair of floats.
Say that the size of the fifo remains reasonably constant.
We can therefore assume that one "operation" on the queue logically consists of one push and one pop.
Say you are comparing 2 methods of handling this: one uses a heap pair and one that uses a naive compare and search.
For the heap method:
Each operation, you push to the list and both heaps, then pop from the list and both heaps. The heap operations are always O(log(n)) and the list operation is O(1), so as N is large, the time complexity of one operation is O(log(N)) average case. It's important to note that the heap operations are always this complexity regardless of whether or not the currently popped element is a min or max element. Thus, N operations has a time complexity of O(N*log(N)).
For the naive method:
Each operation, you push and pop the list, and compare the popped item to the stored min and max. If the item is the same as either one, you search the list either for an item of equal value (in which case you break early) or otherwise through the entire rest of the list, until you find the next best element. You then update the min/max with the next best. This method has O(1) typical case and O(N) worst case (min or max needs an update). It's important to note that for some range of N numbers the number of times you will need to update min and max goes to a constant, and the number of times you won't goes to N. Therefore, N operations has a time complexity of O(N). The naive case is actually better than a more advanced solution.
That said, I don't think heaps can efficiently remove elements, so you'd run into lots of trouble that way.
Thus, consider the following pseudocode:
queue fifo;
float min, max;
void push(float f)
{
if (fifo.size == 0)
{
min = f;
max = f;
}
else if (f > max) max = f;
else if (f < min) min = f;
fifo.push(f);
}
float pop()
{
if (fifo.size == 0) return (*((float *)NULL)); // explode
float f = fifo.pop();
if (fifo.size == 0)
{
min = NaN;
max = NaN;
return f;
}
if (f == max) search_max(fifo);
if (f == min) search_min(fifo);
return f;
}
search_max(queue q)
{
float f = min;
for (element in q)
{
if (element == max) return;
if (element > f) f = element;
}
max = f;
}
search_min(queue q)
{
float f = max;
for (element in q)
{
if (element == min) return;
if (element < f) f = element;
}
min = f;
}