佇列,和棧類似,也是一種操作受限的線性表資料結構。與棧結構不同的是,可以對佇列 2 端操作,要求資料從一端進(入隊),從另一端出(出隊)。佇列遵循 "先進先出" 的原則,即最先進佇列的資料元素,同樣要最先出佇列。
跟棧一樣,佇列可以用陣列來實現,也可以用連結串列來實現。用陣列實現的佇列叫作順序佇列,用連結串列實現的佇列叫作鏈式佇列。
#陣列佇列
class Queue
{
private $_head;
private $_tail;
private $_queue;
private $_queueSize;
public function __construct($size){
$this->_queue = [];
$this->_queueSize = $size;
$this->_head = 0;
$this->_tail = 0;
}
#入隊
public function enQueue( $elem ){
if (!$this->isFull()) {
$this->_queue[$this->_tail] = $elem;
$this->_tail++;
return true;
}
return false;
}
#出隊
public function deQueue(){
if( !$this->isEmpty() ) {
$elem = $this->_queue[$this->_head];
$this->_head ++;
return $elem;
}
return false;
}
#佇列是否為空
public function isEmpty() {
return ( $this->_head == $this->_tail ? true : false );
// return $this->_head == $this->_tail ;
}
#佇列是否已滿
public function isFull(){
return ( $this->_tail === $this->_queueSize ? true : false );
}
}
如上,當不停地入隊和出隊時,head 和 tail 都會後移。當到達陣列最後面時,即使陣列前面仍空餘,也無法入隊操作了。此時,就需要我們對陣列進行遷移(只需要到達陣列最後面時遷移,不需要每次出隊都進行遷移,以此提高效率)。
你可能已經發現,如上所示還是需要做遷移的,如果陣列很大,遷移消耗也很大的。這種情況下,我們可以從頭再開始,也就是頭尾相接的迴圈。我們把佇列這種頭尾相接的順序儲存節後稱為迴圈佇列。
public class CircularQueue {
private $items = [] ;
private $n = 0;
private $head = 0;
private $tail = 0;
public __construct($size) {
$n = $size;
}
public function enqueue($item) {
if (($tail + 1) % $n == $head)
return false;
$items[$tail] = $item;
$tail = ($tail + 1) % $n;
return true;
}
public function dequeue() {
if ($head == $tail)
return false;
$ret = $items[$head];
$head = ($head + 1) % $n;
return $ret;
}
}
資源有限的場景都可以佇列,例如買車票、秒殺、分散式應用的訊息佇列。
本作品採用《CC 協議》,轉載必須註明作者和本文連結