<?php class BinaryHeap { protected $heap; public function __construct() { $this->heap = array(); } public function isEmpty() { return empty($this->heap); } public function count() { // return count($this->heap) - 1; } public function extract() { if ($this->isEmpty()) { throw new RunTimeException(' !'); } // $root = array_shift($this->heap); if (!$this->isEmpty()) { // // $last = array_pop($this->heap); array_unshift($this->heap, $last); // $this->adjust(0); } return $root; } public function compare($item1, $item2) { if ($item1 === $item2) { return 0; } // minheap return ($item1 > $item2 ? 1 : -1); } protected function isLeaf($node) { // 2n + 1 "" return ((2 * $node) + 1) > $this->count(); } protected function adjust($root) { // if (!$this->isLeaf($root)) { $left = (2 * $root) + 1; // $right = (2 * $root) + 2; // $h = $this->heap; // if ( (isset($h[$left]) && $this->compare($h[$root], $h[$left]) < 0) || (isset($h[$right]) && $this->compare($h[$root], $h[$right]) < 0) ) { // if (isset($h[$left]) && isset($h[$right])) { $j = ($this->compare($h[$left], $h[$right]) >= 0) ? $left : $right; } else if (isset($h[$left])) { $j = $left; // } else { $j = $right; // } // list($this->heap[$root], $this->heap[$j]) = array($this->heap[$j], $this->heap[$root]); // // $j $this->adjust($j); } } } }
public function insert($item) { // $this->heap[] = $item; // $place = $this->count(); $parent = floor($place / 2); // while ( $place > 0 && $this->compare( $this->heap[$place], $this->heap[$parent]) >= 0 ) { // list($this->heap[$place], $this->heap[$parent]) = array($this->heap[$parent], $this->heap[$place]); $place = $parent; $parent = floor($place / 2); } }
<?php $heap = new BinaryHeap(); $heap->insert(19); $heap->insert(36); $heap->insert(54); $heap->insert(100); $heap->insert(17); $heap->insert(3); $heap->insert(25); $heap->insert(1); $heap->insert(67); $heap->insert(2); $heap->insert(7);
Array ( [0] => 100 [1] => 67 [2] => 54 [3] => 36 [4] => 19 [5] => 7 [6] => 25 [7] => 1 [8] => 17 [9] => 2 [10] => 3 )
<?php while (!$heap->isEmpty()) { echo $heap->extract() . "n"; }
100 67 54 36 25 19 17 7 3 2 1
<?php class MyHeap extends SplMaxHeap { public function compare($item1, $item2) { return (int) $item1 - $item2; } }
<?php class PriQueue extends SplPriorityQueue { public function compare($p1, $p2) { if ($p1 === $p2) return 0; // , // return ($p1 < $p2) ? 1 : -1; } }
<?php $pq = new PriQueue(); $pq->insert('A', 4); $pq->insert('B', 3); $pq->insert('C', 5); $pq->insert('D', 8); $pq->insert('E', 2); $pq->insert('F', 7); $pq->insert('G', 1); $pq->insert('H', 6); $pq->insert('I', 0); while ($pq->valid()) { print_r($pq->current()); echo "n"; $pq->next(); }
I G E B A C H F D
<?php // $pq->setExtractFlags(SplPriorityQueue::EXTR_PRIORITY); // ( // ) $pq->setExtractFlags(SplPriorityQueue::EXTR_BOTH);
<?php $graph = array( 'A' => array('B', 'F'), 'B' => array('A', 'D', 'E'), 'C' => array('F'), 'D' => array('B', 'E'), 'E' => array('B', 'D', 'F'), 'F' => array('A', 'E', 'C'), );
<?php class Graph { protected $graph; protected $visited = array(); public function __construct($graph) { $this->graph = $graph; } // () 2 public function breadthFirstSearch($origin, $destination) { // foreach ($this->graph as $vertex => $adj) { $this->visited[$vertex] = false; } // $q = new SplQueue(); // $q->enqueue($origin); $this->visited[$origin] = true; // $path = array(); $path[$origin] = new SplDoublyLinkedList(); $path[$origin]->setIteratorMode( SplDoublyLinkedList::IT_MODE_FIFO|SplDoublyLinkedList::IT_MODE_KEEP ); $path[$origin]->push($origin); $found = false; // while (!$q->isEmpty() && $q->bottom() != $destination) { $t = $q->dequeue(); if (!empty($this->graph[$t])) { // foreach ($this->graph[$t] as $vertex) { if (!$this->visited[$vertex]) { // , $q->enqueue($vertex); $this->visited[$vertex] = true; // $path[$vertex] = clone $path[$t]; $path[$vertex]->push($vertex); } } } } if (isset($path[$destination])) { echo " $origin $destination ", count($path[$destination]) - 1, " "; $sep = ''; foreach ($path[$destination] as $vertex) { echo $sep, $vertex; $sep = '->'; } echo "n"; } else { echo " $origin $destinationn"; } } }
<?php $g = new Graph($graph); // D C $g->breadthFirstSearch('D', 'C'); // : // D C 3 // D->E->F->C // B F $g->breadthFirstSearch('B', 'F'); // : // B F 2 // B->A->F // A C $g->breadthFirstSearch('A', 'C'); // : // A C 2 // A->F->C // A G $g->breadthFirstSearch('A', 'G'); // : // A G
<?php $graph = array( 'A' => array('B' => 3, 'D' => 3, 'F' => 6), 'B' => array('A' => 3, 'D' => 1, 'E' => 3), 'C' => array('E' => 2, 'F' => 3), 'D' => array('A' => 3, 'B' => 1, 'E' => 1, 'F' => 2), 'E' => array('B' => 3, 'C' => 2, 'D' => 1, 'F' => 5), 'F' => array('A' => 6, 'C' => 3, 'D' => 2, 'E' => 5), );
<?php class Dijkstra { protected $graph; public function __construct($graph) { $this->graph = $graph; } public function shortestPath($source, $target) { // $d = array(); // "" $pi = array(); // $Q = new SplPriorityQueue(); foreach ($this->graph as $v => $adj) { $d[$v] = INF; // $pi[$v] = null; // foreach ($adj as $w => $cost) { // $Q->insert($w, $cost); } } // - 0 $d[$source] = 0; while (!$Q->isEmpty()) { // $u = $Q->extract(); if (!empty($this->graph[$u])) { // foreach ($this->graph[$u] as $v => $cost) { // $alt = $d[$u] + $cost; // if ($alt < $d[$v]) { $d[$v] = $alt; // update minimum length to vertex $pi[$v] = $u; // } } } } // // $S = new SplStack(); // $u = $target; $dist = 0; // while (isset($pi[$u]) && $pi[$u]) { $S->push($u); $dist += $this->graph[$u][$pi[$u]]; // $u = $pi[$u]; } // , if ($S->isEmpty()) { echo " $source $targetn"; } else { // // (LIFO) $S->push($source); echo "$dist:"; $sep = ''; foreach ($S as $v) { echo $sep, $v; $sep = '->'; } echo "n"; } } }
<?php $g = new Dijkstra($graph); $g->shortestPath('D', 'C'); // 3:D->E->C $g->shortestPath('C', 'A'); // 6:C->E->D->A $g->shortestPath('B', 'F'); // 3:B->D->F $g->shortestPath('F', 'A'); // 5:F->D->A $g->shortestPath('A', 'G'); // A G
Source: https://habr.com/ru/post/190474/
All Articles