This is a difficult question. Consider the following:
Say that the size of your fifo at any given time is N. Say that you track min and max only with a pair of floats. Let's say that the fifo size remains fairly constant.
Thus, we can assume that one โoperationโ in the queue logically consists of one click and one pop function.
Suppose you are comparing 2 methods of handling this: one that uses a bunch of pairs and one that uses naive comparison and search.
For the heap method:
Each operation, you click on the list and both heaps, and then drop out of the list and both heaps. The heap operations are always O (log (n)), and the list operation is O (1), since N is large, the time complexity of one operation is O (log (N)) the average case. It is important to note that heap operations are always such complexity, regardless of whether the current poped element is minimum or maximum. Thus, N operations has a time complexity of O (N * log (N)).
For the naive method:
Each operation, you click and publish the list, and compare the pop-up element with the saved minimum and max. If the item is the same as one, you search the list for either an item with the same value (in this case, you will break early) or otherwise through the rest of the list until you find the next best item. Then you update min / max with the next best. This method has an O (1) typical case and O (N) the worst case (min or max needs to be updated). It is important to note that for a certain range of numbers N the number of times you need to update min and max goes to a constant, and the number of times you do not go to N. Therefore, N operations have the time complexity of NA). A naive case is actually better than a more advanced solution.
However, I don't think heaps can remove elements efficiently, so you will run into a lot of trouble this way.
Thus, consider the following pseudo-code:
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; }