如何剥离或切片SplHeap(也称为SplMaxHeap、SplMinHeap)的底部项目


How to strip or slice the bottom items of a SplHeap (also SplMaxHeap, SplMinHeap)?

我有一个包含30个项目的SplMaxHeap。现在我想去掉最后10个。如何以体面和高效的方式做到这一点?

到目前为止,我看到的唯一解决方案是将前20个项目复制到一个新堆中,或者将堆转换为一个数组,使用array_slice并将它们也放在一个新的堆中。

我甚至看不出有什么方法可以从堆里得到一些东西,而不是从顶部。

我想这是因为堆的一般设计的限制?我也在考虑使用DoublyLinkedList,但我错过了自动排序。

一种方法是创建一个从SPL堆派生的新类,该类在插入时只保留顶部(或底部,取决于堆)n项。

一个超级基本的例子可能看起来像:

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

Tobias Schlitt在2010年的文章"堆,堆,万岁!"中对此进行了进一步的讨论。

问题是SPLHeap内部没有"底部"。元素存储在树状结构中。术语"底部"变得有点没有意义,然而,树总是有一个"顶部",这正是SPLHeap可以返回的。

如果您有少量的项,您可能会选择其他数据结构(即使是简单的数组也足够了)。插入元素可能需要一些额外的时间(这是树非常有效的地方),但维护顶部和底部也很便宜(就像SplDoubleLinkedList一样)。

除非您存储了数以万计的元素,否则可能需要跳过SplHeap。

注意:在PHP中创建一个fixedHeap结构已经足够琐碎了,但我认为它不会更快。基准测试,以检查哪些内容满足您的需求。