SplPriorityQueue を継承したらちょっと複雑なPriorityQueueが実装したりできるのですが、なんかたまにうまく動かないことがあります。
正常に動く例: 長方形を面積が大きい順に並べる
SplPriorityQueue を継承して、 insertRectangle というメソッドで面積を計算してinsertします。
<?php /** 長方形クラス */ class Rectangle { public $width, $height; public function __construct($width, $height) { $this->width = $width; $this->height = $height; } } /** Priority Queue */ class MyPriorityQueue extends SplPriorityQueue { /** 面積を計算してそれを優先度としてinsertするメソッド */ public function insertRectangle(Rectangle $rectangle) { // 面積をpriorityに突っ込む $this->insert($rectangle, $rectangle->width * $rectangle->height); } } $queue = new MyPriorityQueue(); // 長方形を突っ込む $queue->insertRectangle(new Rectangle(2, 4)); $queue->insertRectangle(new Rectangle(3, 3)); $queue->insertRectangle(new Rectangle(1, 7)); // 面積が大きい順に取り出される筈 while(!$queue->isEmpty()) { var_dump($queue->extract()); }
これを実行すると
$ php PriorityQueue3.php [master] object(Rectangle)#3 (2) { ["width"]=> int(3) ["height"]=> int(3) } object(Rectangle)#2 (2) { ["width"]=> int(2) ["height"]=> int(4) } object(Rectangle)#4 (2) { ["width"]=> int(1) ["height"]=> int(7) }
ちゃんと面積が大きい順に出てきますね。
正常に動かない例: 長方形を面積が小さい順に並べる
今度は面積が小さい順にするためにcompareメソッドをオーバーライドします。
/** Priority Queue */ class MyPriorityQueue extends SplPriorityQueue { /** priorityが低いものから取り出すようにする */ public function compare($priority1, $priority2) { if($priority1 === $priority2) return 0; $priority1 < $priority2 ? -1 : 1; } /** 面積を計算してそれを優先度としてinsertするメソッド */ public function insertRectangle(Rectangle $rectangle) { // 面積をpriorityに突っ込む $this->insert($rectangle, $rectangle->width * $rectangle->height); } }
このようにします。これで
// 長方形を突っ込む $queue->insertRectangle(new Rectangle(2, 4)); $queue->insertRectangle(new Rectangle(3, 3)); $queue->insertRectangle(new Rectangle(1, 7));
こうすると
$ php PriorityQueue3.php [master] object(Rectangle)#2 (2) { ["width"]=> int(2) ["height"]=> int(4) } object(Rectangle)#4 (2) { ["width"]=> int(1) ["height"]=> int(7) } object(Rectangle)#3 (2) { ["width"]=> int(3) ["height"]=> int(3) }
面積が小さい順にソートされず、かといって入れた順とも違う順で出てきてしまいます。
んー、何か継承して複数メソッドをオーバーライドするとバグるのか、継承の仕方とかが良くないのか。PHPの闇な感じがあります。もし何か実装ミスとかに気づいた人がいたら教えてほしいです。
- 作者: 大重美幸
- 出版社/メーカー: ソーテック社
- 発売日: 2016/12/20
- メディア: Kindle版
- この商品を含むブログを見る