SplStackとSplQueueでスタック・キューを素直に書く
SplStackとSplQueueは、SPLが提供するデータ構造クラスです。それぞれLIFOのスタックとFIFOのキューを表し、配列での代用より構造の意図を明示できる書き方ですね。
配列で代用すると意図が伝わりにくい
PHP は配列が万能なので、スタックやキューも array_push / array_pop / array_shift の組み合わせで書けてしまいます。ただ、これだと「この配列はスタックとして使っている」という意図がコードから読み取りにくいんですね。SPL の専用クラスを使うと、そこがはっきりします。
// 配列での代用:意図が暗黙的
$stack = [];
array_push($stack, 'a');
$top = array_pop($stack);
SplStackはLIFOを明示する
SplStack は後入れ先出し(LIFO)の構造で、push と pop で操作します。名前からして役割が明確なので、履歴の戻る処理や括弧の対応チェックのような場面で使うと読み手に優しいですね。
$stack = new SplStack();
$stack->push('a');
$stack->push('b');
echo $stack->top(); // b(覗くだけ)
echo $stack->pop(); // b(取り出す)
echo count($stack); // 1
SplQueueはFIFOで先入れ先出し
SplQueue は先入れ先出し(FIFO)で、enqueue で入れて dequeue で取り出します。ジョブの順次処理や幅優先探索の待ち行列に向いています。array_shift はインデックスの振り直しが走るのに対し、SplQueue は内部的に双方向リストなので、大量要素の取り出しでも素直な性能になりやすいのが利点ですね。
$queue = new SplQueue();
$queue->enqueue('job1');
$queue->enqueue('job2');
while (!$queue->isEmpty()) {
echo $queue->dequeue(); // job1, job2 の順
}
まとめ
配列でも同じことはできますが、SplStack と SplQueue を使うと構造の意図がコードに現れて、後から読む人(と未来の自分)が理解しやすくなると思います。どちらも Iterator や Countable を実装しているので foreach や count も効きます。データ構造の役割をはっきりさせたいときの選択肢として持っておくといいですね。
よくある質問
Q. 配列でスタックやキューを書くのと何が違いますか。
A. 動作は同じですが、SplStack/SplQueueを使うと「スタックとして使っている」という意図がコードに現れて読みやすくなります。
Q. foreachやcountは使えますか。
A. どちらもIteratorとCountableを実装しているので、foreachやcountがそのまま効きます。