У меня есть SplMaxHeap
с 30 элементами. Теперь я хочу снять последние 10. Как это сделать достойно и эффективно?
Единственные решения, которые я вижу до сих пор, - это скопировать первые 20 элементов в новую кучу или преобразовать кучу в массив, использовать array_slice
и поместить их в новую кучу.
Я даже не вижу способа получить что-то из кучи не сверху.
Думаю, причина в этом - ограничение общего дизайна кучи? Я также думал использовать DoublyLinkedList
, но там мне не хватает автоматической сортировки.
Проблема в том, что внутри SPLHeap нет "дна". Элементы хранятся в древовидной структуре. Термин "нижний" становится немного бессмысленным, однако всегда есть "вершина" дерева, и это именно то, что может вернуть SPLHeap.
Если у вас есть небольшое количество элементов, вы можете уйти с альтернативными структурами данных (даже простых массивов будет достаточно). Вставка элементов может занять немного дополнительное время (это то, где деревья очень эффективны), но сохранение верхней и нижней части снова дешево (например, SplDoubleLinkedList
).
Если вы не храните десятки тысяч элементов, вы можете пропустить SplHeap для этого.
Примечание. Это достаточно тривиально, чтобы создать структуру fixedHeap в самом PHP, но я считаю, что это было бы не быстрее. Тест, чтобы проверить, что удовлетворяет ваши потребности.
Один из подходов заключается в создании нового класса, полученного из кучи SPL, который при вставке сохраняет только верхние (или нижние, в зависимости от кучи) n элементов.
Супер-базовый пример может выглядеть примерно так:
class Top100 extends SplMinHeap
{
protected $limit = 100;
public function insert($value)
{
parent::insert($value);
while (count($this) > $this->limit) {
$this->extract();
}
}
}
Это обсуждается далее в статье Тобиаса Шлитта 2010 " Куча, куча, ура! ".