Кучи на основе массива кажутся идеальными для ваших целей. Я не уверен, почему вы их отвергли.
Вы используете максимальную кучу.
Скажем, у вас есть куча N элементов (реализованная в виде массива), которая содержит N самых маленьких элементов, которые мы когда-либо видели.
Когда элемент входит, вы проверяете максимальное (O (1) время) и отклоняете, если оно больше.
Если входящее значение меньше, вы изменяете корень на новое значение и уменьшаете это измененное значение - время O (log N) в худшем случае.
Процесс sift-down прост: начиная с root, на каждом шаге вы обмениваетесь этим значением с его более крупным потомком, пока не восстановится свойство max-heap.
Таким образом, вам не нужно будет удалять , что вам, вероятно, придется, если вы используете std :: priority_queue. В зависимости от реализации std :: priority_queue это может привести к выделению / освобождению памяти.
Таким образом, вы можете иметь следующий код:
- Выделенный массив размера N.
- Заполните его первыми N элементами, которые вы видите.
- heapify (вы должны найти это в стандартных учебниках, он использует sift-down). Это O (N).
- Теперь любой новый элемент, который вы получаете, вы либо отклоняете в O (1) раз, либо вставляете, отсеивая в худшем случае O (logN).
В среднем, тем не менее, вам, вероятно, не придется полностью уменьшать новое значение, и оно может быть лучше, чем среднее время вставки O (logn) (хотя я не пытался это доказать). *
Вы выделяете массив размера N только один раз, и любая вставка выполняется путем замены элементов массива, поэтому динамическое выделение памяти после этого не происходит.
Посетите вики-страницу с псевдокодом для heapify и sift-down: http://en.wikipedia.org/wiki/Heapsort