为什么SplPriorityQueue类是队列(概念)

时间:2014-08-27 08:56:30

标签: php spl

基本上SplPriorityQueue类是使用max heap algoritm的堆。

我不明白为什么文档应该是prioritized queue,因为queue FIFO 集合(先进先出) - 但是因为SplPriorityQueue它取决于priority variable的比较函数,为什么它是一个队列?

为什么课程不仅仅是SplPriorityCollection?!

- > SplPriorityQueue documentation


Mark Ba​​ker的启发评论我测试了比较功能的行为,当所有项目的优先级相同时,结果表明,具有相同优先级的集合不是 FIFO < /强>

$objPQ = new SplPriorityQueue(); 

$objPQ->insert('A', 1); 
$objPQ->insert('B', 1); 
$objPQ->insert('C', 1); 
$objPQ->insert('D', 1); 
$objPQ->insert('E', 1); 
$objPQ->insert('F', 1);
$objPQ->insert('G', 1);


foreach($objPQ as $val) {
    echo $val . "\n";
}

输出

A G F E D C B

2 个答案:

答案 0 :(得分:5)

  

基本上SplPriorityQueue类是使用max heap algoritm [sic]的堆。

使用堆的事实是实现细节,使用堆不是必需的。优先级队列数据结构也不是PHP独有的(不是有人说它是!)。希望维基百科的以下简短引用有助于:

  

虽然优先级队列通常使用堆来实现,但它们在概念上与堆不同。优先级队列是一个抽象概念,如“列表”或“地图”;就像列表可以用链表或数组实现一样,优先级队列可以用堆或各种其他方法实现,例如无序数组。

     

- http://en.wikipedia.org/wiki/Priority_queue


同一来源也有以下说法:

  

如果两个元素具有相同的优先级,则根据队列中的顺序提供它们

这与SplPriorityQueue的作者在PHP错误报告([Won't Fix] Bug #53710 Data registered with equal priority not returned in expected order)中的评论相反,后者描述了具有相同优先级值的迭代(错误)行为。

  

没有这样的保证。你唯一的保证   SplPriorityQueue是你不会出现乱序的元素。元素与   以任意顺序提取相同的优先级,其余的是实现   依赖

上述错误报告的作者继续撰写了一篇博客文章Taming SplPriorityQueue,该帖子使用以下技术实施可预测的队列顺序:

namespace Foo;

class SplPriorityQueue extends \SplPriorityQueue
{
    protected $queueOrder = PHP_INT_MAX;

    public function insert($datum, $priority)
    {
        if (is_int($priority)) {
            $priority = array($priority, $this->queueOrder--);
        }
        parent::insert($datum, $priority);
    }
}

答案 1 :(得分:1)

SPLPriorityQueue看起来更像是一个堆而不是一个队列,应该用它作为队列的FIFO方面是不适用的

但是,可以通过修改插入来调整比较函数中使用的值

来恢复FIFO
class PQtest extends SplPriorityQueue 
{ 
    protected $serial = PHP_INT_MAX;

    public function insert($value, $priority) {
        parent::insert($value, array($priority, $this->serial--));
    }

    public function compare($priority1, $priority2) 
    { 
        if ($priority1 === $priority2) return 0; 
        return $priority1 < $priority2 ? -1 : 1; 
    } 
} 

$objPQ = new PQtest(); 

$objPQ->insert('A',1); 
$objPQ->insert('B',1); 
$objPQ->insert('C',1); 
$objPQ->insert('D',1); 
$objPQ->insert('E',1); 
$objPQ->insert('F',1); 

echo "COUNT->".$objPQ->count().PHP_EOL; 

//mode of extraction 
$objPQ->setExtractFlags(PQtest::EXTR_BOTH); 

//Go to TOP 
$objPQ->top(); 

while($objPQ->valid()){ 
    print_r($objPQ->current()); 
    echo PHP_EOL; 
    $objPQ->next(); 
}