這篇文章運用簡單易懂的例子給大家介紹什么是PHP優先級隊列,代碼非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
PHP 的 SPL 庫內置了 SplPriorityQueue優先級隊列,并且是以Heap數據結構實現的,默認為MaxHeap模式,即priority越大越優先出隊,同時可以通過重寫compare方法來使用MinHeap(優先級越低越優先出隊,場景貌似很少吧)。
SplPriorityQueue
堆特性
這里需要注意并理解:SplPriorityQueue是以堆數據結構來實現的,當我們出隊時會拿出堆頂的元素,此時堆的特性被破壞,堆會進行相應的調整至穩定態(MaxHeap or MinHeap),即會將最后一個元素替換到堆頂,然后進行穩定態驗證,不符合堆特性則繼續調整,或者我們就得到了一個穩定態的堆,所以當優先級相同,出隊順序并不會按照入隊順序。
源碼示例:
<?php $splPriorityQueue = new \SplPriorityQueue(); // 設定返回數據的meta信息 // \SplPriorityQueue::EXTR_DATA 默認 只返回數 // \SplPriorityQueue::EXTR_PRIORITY 只返回優先級 // \SplPriorityQueue::EXTR_BOTH 返回數據和優先級 // $splPriorityQueue->setExtractFlags(\SplPriorityQueue::EXTR_DATA); $splPriorityQueue->insert("task1", 1); $splPriorityQueue->insert("task2", 1); $splPriorityQueue->insert("task3", 1); $splPriorityQueue->insert("task4", 1); $splPriorityQueue->insert("task5", 1); echo $splPriorityQueue->extract() . PHP_EOL; echo $splPriorityQueue->extract() . PHP_EOL; echo $splPriorityQueue->extract() . PHP_EOL; echo $splPriorityQueue->extract() . PHP_EOL; echo $splPriorityQueue->extract() . PHP_EOL; //執行結果 task1 task5 task4 task3 task2
可以看到,雖然 5 個任務的優先級相同,但隊列并沒有按照入隊順序返回數據,因為堆的特性使然:
1、入隊 task1, task2, task3, task4, task5,因為優先級相同,所以堆一直處于穩定態。
2、出隊,得 task1,堆先將結構調整為 task5, task2, task3, task4,已然達到了穩定態。
3、出隊,得 task5,堆先將結構調整為 task4, task2, task3,已然達到了穩定態。
4、出隊,得 task4,堆先將結構調整為 task3, task2,已然達到了穩定態。
5、出隊,得 task3,堆先將結構調整為 task2,已然達到了穩定態。
4、出隊,得 task2。
Iterator, Countable
SplPriorityQueue實現了 Iterator, Countable接口,所以我們可以foreach/count函數操作它,或者使用rewind,valid,current,next/count方法。
注意,因為是堆實現,所以rewind方法是一個no-op沒有什作用的操作,因為頭指針始終指向堆頂,即current始終等于top,不像List只是游走指針,出隊是會刪除堆元素的,extract = current + next(current出隊,從堆中刪除)。
<?php $splPriorityQueue = new \SplPriorityQueue(); $splPriorityQueue->insert("task1", 1); $splPriorityQueue->insert("task2", 2); $splPriorityQueue->insert("task3", 1); $splPriorityQueue->insert("task4", 4); $splPriorityQueue->insert("task5", 5); echo "Countable: " . count($splPriorityQueue) . PHP_EOL; // 迭代的話會刪除隊列元素 current 指針始終指向 top 所以 rewind 沒什么意義 for ($splPriorityQueue->rewind(); $splPriorityQueue->valid();$splPriorityQueue->next()) { var_dump($splPriorityQueue->current()); var_dump($splPriorityQueue->count()); $splPriorityQueue->rewind(); } var_dump("is empty:" . $splPriorityQueue->isEmpty());
Extract出隊
extract 出隊更為友好,即始終返回優先級最高的元素,優先級相投時會以堆調整的特性返回數據。
<?php $splPriorityQueue = new \SplPriorityQueue(); // data priority $splPriorityQueue->insert("task1", 1); $splPriorityQueue->insert("task2", 2); $splPriorityQueue->insert("task3", 1); $splPriorityQueue->insert("task4", 4); $splPriorityQueue->insert("task5", 5); echo "Countable: " . count($splPriorityQueue) . PHP_EOL; while (! $splPriorityQueue->isEmpty()) { var_dump($splPriorityQueue->extract()); echo $splPriorityQueue->count() . PHP_EOL; }
自定義優先級處理方式
重寫compare方法定義自己的優先級處理機制。
<?php class CustomedSplPriorityQueue extends SplPriorityQueue { public function compare($priority1, $priority2): int { // return $priority1 - $priority2;//高優先級優先 return $priority2 - $priority1;//低優先級優先 } } $splPriorityQueue = new \CustomedSplPriorityQueue(); $splPriorityQueue->setExtractFlags(SplPriorityQueue::EXTR_BOTH); $splPriorityQueue->insert("task1", 1); $splPriorityQueue->insert("task2", 2); $splPriorityQueue->insert("task3", 1); $splPriorityQueue->insert("task4", 4); $splPriorityQueue->insert("task5", 5); echo "Countable: " . count($splPriorityQueue) . PHP_EOL; while (!$splPriorityQueue->isEmpty()) { var_dump($splPriorityQueue->extract()); }
關于什么是PHP優先級隊列就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
另外有需要云服務器可以了解下創新互聯scvps.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業上云的綜合解決方案,具有“安全穩定、簡單易用、服務可用性高、性價比高”等特點與優勢,專為企業上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。
本文名稱:什么是PHP優先級隊列-創新互聯
文章路徑:http://vcdvsql.cn/article42/cssehc.html
成都網站建設公司_創新互聯,為您提供網站設計、品牌網站設計、建站公司、動態網站、標簽優化、企業網站制作
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯