Как раздеть или нарезать нижние элементы SplHeap (также SplMaxHeap, SplMinHeap)?

0

У меня есть SplMaxHeap с 30 элементами. Теперь я хочу снять последние 10. Как это сделать достойно и эффективно?

Единственные решения, которые я вижу до сих пор, - это скопировать первые 20 элементов в новую кучу или преобразовать кучу в массив, использовать array_slice и поместить их в новую кучу.

Я даже не вижу способа получить что-то из кучи не сверху.

Думаю, причина в этом - ограничение общего дизайна кучи? Я также думал использовать DoublyLinkedList, но там мне не хватает автоматической сортировки.

  • 0
    @PaulCrovella Я вижу и понимаю. Я просто надеюсь, что кто-то найдет умный способ обойти это ограничение дизайна. Если нет хорошего ответа, я знаю, по крайней мере, что мне не нужно пробовать это, и что я должен использовать пользовательскую структуру данных.
Теги:
heap
slice
spl

2 ответа

1

Проблема в том, что внутри SPLHeap нет "дна". Элементы хранятся в древовидной структуре. Термин "нижний" становится немного бессмысленным, однако всегда есть "вершина" дерева, и это именно то, что может вернуть SPLHeap.

Если у вас есть небольшое количество элементов, вы можете уйти с альтернативными структурами данных (даже простых массивов будет достаточно). Вставка элементов может занять немного дополнительное время (это то, где деревья очень эффективны), но сохранение верхней и нижней части снова дешево (например, SplDoubleLinkedList).

Если вы не храните десятки тысяч элементов, вы можете пропустить SplHeap для этого.

Примечание. Это достаточно тривиально, чтобы создать структуру fixedHeap в самом PHP, но я считаю, что это было бы не быстрее. Тест, чтобы проверить, что удовлетворяет ваши потребности.

1

Один из подходов заключается в создании нового класса, полученного из кучи SPL, который при вставке сохраняет только верхние (или нижние, в зависимости от кучи) n элементов.

Супер-базовый пример может выглядеть примерно так:

class Top100 extends SplMinHeap
{
    protected $limit = 100;
    public function insert($value)
    {
        parent::insert($value);
        while (count($this) > $this->limit) {
            $this->extract();
        }
    }
}

Это обсуждается далее в статье Тобиаса Шлитта 2010 " Куча, куча, ура! ".

  • 0
    Проблема в том, что теперь вы больше не можете извлекать вершину, если не возьмете их все и не перевернете их.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню