Skip to content

Zeroplex 生活隨筆

軟體開發、伺服器和生活瑣事

小 縮小字型大小。 中 重設字型大小。 大 放大字型大小。

PHP SplPriorityQueue …. WTF!

Posted on 2018 年 8 月 29 日2021 年 3 月 12 日 By 日落 在〈PHP SplPriorityQueue …. WTF!〉中尚無留言

我還以為 PHP SPL 的類別應該實作上應該有比較嚴謹,但 … 我錯了 QQ

先來看一下 SplPriorityQueue 的官方文件定義:
public void insert ( mixed $value , mixed $priority )
priority 和我預期的不一樣,原本以為只能放數字 (numbers) 但這邊的 priority type hint 卻標示為「mixed」,表示 priority 可以是任何資料型態 …?

先從最一般的 case 來測試吧:

$q = new SplPriorityQueue();

$q->insert(1, 'A');
$q->insert(2, 'B');
$q->insert(3, 'C');
$q->insert(4, 'D');
$q->insert(5, 'E');

while ($q->count() > 0) {
    echo $q->extract() . PHP_EOL;
}

output:

5
4
3
2
1

看起來會用 ASCII 數值來比較,數值大的優先 dequeue。看起來沒問題。


再來看一下遇到相同 priority 中有多個數值時,到底會發生什麼事:

$q = new SplPriorityQueue();

$q->insert(1, 1);
$q->insert(2, 1);
$q->insert(3, 1);
$q->insert(4, 1);
$q->insert(5, 1);

while ($q->count() > 0) {
    echo $q->extract() . PHP_EOL;
}

output:

1
5
4
3
2

「5, 4, 3, 2」還算正常,但是為什麼「1」會突然跑到最前面!?


最後,priority 真的可以放其他資料型態嗎?為了更清楚的看到執行結果,我這邊改使用 psysh 來操作:

Psy Shell v0.8.18 (PHP 7.1.18 — cli) by Justin Hileman
Unable to check for updates
>>> $q = new SplPriorityQueue();
=> SplPriorityQueue {#201
     heap: [],
   }
>>> $q->insert(1, [1, 2, 3]);
=> true
>>> $q->insert(2, []);
=> true
>>> $q->insert(3, new Exception())
=> true

靠北啊,Exception 也可以當作 priority 使用 ….

>>> while ($q->count() > 0) {
... echo $q->extract() . PHP_EOL;
... }
3
1
2

…. 我不想講了。

總之,若你要使用 SplPriorityQueue,請注意 undefined behavior。

Reference:

  • php – Why SplPriorityQueue keys are reversed? – Stack Overflowhttps://stackoverflow.com/questions/21446898/why-splpriorityqueue-keys-are-reversed
  • php – How SplPriorityQueue works when priority is not an integer? – Stack Overflowhttps://stackoverflow.com/questions/15851726/how-splpriorityqueue-works-when-priority-is-not-an-integer
  • 有人重新實作了自己的 priority queue –  ezimuel/FastPriorityQueue
    https://github.com/ezimuel/FastPriorityQueue
Tags:PHP

文章導覽

Previous Post: type (in Bash) 來判別 shell 實際執行的命令
Next Post: 電腦字型的授權範圍

發佈留言 取消回覆

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *


其他

關於我  (About me)

小額贊助

  文章 RSS Feed

  留言 RSS Feed

Apache AWS Bash C/C++ Docker FreeBSD GCP Git Google Java JavaScript Laravel Linux Microsoft MSSQL MySQL Nginx PHP PHPUnit PostgreSQL Python Qt Ubuntu Unix Vim Web Windows WordPress XD 作業系統 分享 好站推薦 專題 攝影 新奇搞笑 新聞 旅遊 生活雜記 程式設計 網路架站 網頁設計 資訊學習 資訊安全 遊戲 音樂


創用 CC 授權條款
本著作係採用創用 CC 姓名標示-相同方式分享 4.0 國際 授權條款授權.