# SplPriorityQueue - 优先队列

[官方地址](http://php.net/manual/zh/class.splpriorityqueue.php)

SplPriorityQueue是基于堆实现的.

> SplQueue(队列)类就是实现队列操作，和栈一样，它也可以继承双链表(SplDoublyLinkedList)轻松实现。

优先队列也是非常实用的一种数据结构，可以通过加权对值进行排序，由于排序在php内部实现，业务代码中将精简不少而且更高效。通过`SplPriorityQueue::setExtractFlags(int $flag)`设置提取方式可以提取数据（等同最大堆）、优先级、和两者都提取的方式。

## 类摘要

```php
SplPriorityQueue implements Iterator , Countable {
    public __construct ( void )
    public int compare ( mixed $priority1 , mixed $priority2 ) // 比较优先级，以便在筛选时将元素正确放置在堆中。
    public int count ( void ) // 计算队列中元素的数量。
    public mixed current ( void ) // 返回迭代器指向的当前节点
    public mixed extract ( void ) // 从堆顶部提取一个节点并向上移动
    public void insert ( mixed $value , mixed $priority ) // 在队列中插入一个元素
    public bool isEmpty ( void ) //检查队列是否为空。
    public mixed key ( void ) // 返回当前节点索引(key键)
    public void next ( void ) // 移动到下一个节点
    public void recoverFromCorruption ( void ) // 从损坏的状态恢复，并允许队列中的其他操作。
    public void rewind ( void ) // 将迭代器倒回起始
    public void setExtractFlags ( int $flags ) // 设置提取模式
    public mixed top ( void ) // 从队列顶部的节点上看一眼
    public bool valid ( void ) // 检查队列是否包含多个节点。
}
```

可以看到SplPriorityQueue实现了Iterator（迭代器）

其中：compare方法比较时：

* priority1 > priority2 ,返回1
* priority1 = priority2 ,返回0
* priority1 < priority2 ,返回-1

> 注意：通过extract,next方法操作，rewind 没用回到当初的队列起始位置

## 简单示例：

```php
$pq = new SplPriorityQueue();

$pq->insert('a', 10);
$pq->insert('b', 1);
$pq->insert('c', 8);
$pq->insert('d', 3);

echo $pq->count() .PHP_EOL; //4
echo $pq->current() . PHP_EOL; //a
echo $pq->current() . PHP_EOL; //a 因为迭代器的指针没用移动
echo $pq->next() . PHP_EOL;  //迭代器移动会影响到ｗhile的输出
echo $pq->current() . PHP_EOL; //c 
echo $pq->compare(10, 1) . PHP_EOL; //1  对优先级的数值进行比较
//echo $pq->extract() . PHP_EOL; // c
//echo $pq->extract() . PHP_EOL; // d ,注意迭代器的指针发生了变化，会影响到ｗhile的输出
//echo $pq->top() . PHP_EOL;  // b,extract操作导致指针已经移动将d扔出，所以此处队列的顶端是b

/**
 * 设置元素出队模式
 * SplPriorityQueue::EXTR_DATA 仅提取值
 * SplPriorityQueue::EXTR_PRIORITY 仅提取优先级
 * SplPriorityQueue::EXTR_BOTH 提取数组包含值和优先级
 */
echo "while:" . PHP_EOL;
$pq->rewind();
$pq->setExtractFlags(SplPriorityQueue::EXTR_DATA);
//$pq->setExtractFlags(SplPriorityQueue::EXTR_PRIORITY);
//$pq->setExtractFlags(SplPriorityQueue::EXTR_BOTH);

while($pq->valid()) {
    echo 'key:' . $pq->key() . PHP_EOL; // 3 2 1 0 
    print_r($pq->current()). PHP_EOL;//a c d b
    $pq->next();
}
```

上面输出结果：

* 1.EXTR\_DATA 仅提取值, 则输出：`a c b`
* 2.EXTR\_PRIORITY 仅提取优先级, 则输出：`10 8 1`
* 3.EXTR\_BOTH 提取数组包含值和优先级, 则输出：`Array ( [data] => a [priority] => 10 ) Array ( [data] => c [priority] => 8 ) Array ( [data] => b [priority] => 1 )`

## 资料

这方面zendframework的底层有所重写实现，可以参考

<https://github.com/zendframework/zend-stdlib/blob/master/src/SplPriorityQueue.php>

<https://github.com/zendframework/zend-stdlib/blob/master/src/PriorityQueue.php>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://phper.shujuwajue.com/biao-zhun-php-ku-ff08-spl/shu-ju-jie-gou/splpriorityqueue-you-xian-dui-lie.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
