PriorityQueue.class.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************************
00003  *   Copyright (C) 2009 by Denis M. Gabaidulin                             *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Lesser General Public License as        *
00007  *   published by the Free Software Foundation; either version 3 of the    *
00008  *   License, or (at your option) any later version.                       *
00009  *                                                                         *
00010  ***************************************************************************/
00011 
00012     final class PriorityQueue
00013     {
00014         private $heap           = array(0);
00015         private $heapSize       = 0;
00016         private $cmpFunction    = null;
00017         
00018         public function getLength()
00019         {
00020             return $this->heapSize;
00021         }
00022         
00023         public function first()
00024         {
00025             return $this->heap[1];
00026         }
00027         
00028         public static function create($unsortedData = array())
00029         {
00030             return new self($unsortedData);
00031         }
00032         
00033         public function __construct($unsortedData = array())
00034         {
00035             $this->heap = array_merge($this->heap, $unsortedData);
00036             
00037             $this->heapSize = count($this->heap) - 1;
00038             
00039             $this->buildMaxHeap();
00040         }
00041         
00042         /*
00043         function cmp($one, $two)
00044         {
00045             if ($one['d'] == $two['d'])
00046                 return 0;
00047             
00048             return ($one['d'] < $two['d']) ? -1 : 1;
00049         }
00050         */
00051         public function setCmpFunction($function)
00052         {
00053             $this->cmpFunction = $function;
00054             
00055             return $this;
00056         }
00057         
00058         public function parent($index)
00059         {
00060             return $index >> 1;
00061         }
00062         
00063         public function left($index)
00064         {
00065             return $index << 1;
00066         }
00067         
00068         public function right($index)
00069         {
00070             return 1 + ($index << 1);
00071         }
00072         
00073         public function maxHeapify($index)
00074         {
00075             $left = $this->left($index);
00076             $right = $this->right($index);
00077             
00078             $largest = null;
00079             
00080             $cmp = $this->cmpFunction;
00081             
00082             if ($left <= $this->heapSize && $cmp($this->heap[$left], $this->heap[$index]) == 1)
00083                 $largest = $left;
00084             else
00085                 $largest = $index;
00086                 
00087             if ($right <= $this->heapSize && $cmp($this->heap[$right], $this->heap[$largest]) == 1)
00088                 $largest = $right;
00089             
00090             if ($largest != $index) {
00091                 $this->swapElts($index, $largest);
00092                 
00093                 $this->maxHeapify($largest);
00094             }
00095         }
00096         
00097         public function buildMaxHeap()
00098         {
00099             for ($i = $this->heapSize / 2; $i > 0; $i--) {
00100                 $this->maxHeapify($i);
00101             }
00102         }
00103         
00104         public function pop()
00105         {
00106             if ($this->heapSize == 0)
00107                 return null;
00108             
00109             $max = $this->heap[1];
00110             
00111             $this->heap[1] = $this->heap[$this->heapSize--];
00112             
00113             $this->maxHeapify(1);
00114             
00115             return $max;
00116         }
00117         
00118         public function push($elt)
00119         {
00120             ++$this->heapSize;
00121             
00122             $this->heap[$this->heapSize] = PrimitiveInteger::SIGNED_MIN;
00123             
00124             $index = $this->heapSize;
00125             
00126             $this->heap[$index] = $elt;
00127             
00128             $cmp = $this->cmpFunction;
00129             
00130             while (
00131                 $index > 1
00132                 &&
00133                     $cmp(
00134                         $this->heap[$this->parent($index)],
00135                         $this->heap[$index]
00136                     ) == -1
00137             ) {
00138                 $this->swapElts($index, $this->parent($index));
00139                 
00140                 $index = $this->parent($index);
00141             }
00142         }
00143         
00144         public function delete($index)
00145         {
00146             $this->heap[$index] = $this->heap[$this->heapSize];
00147             
00148             unset($this->heap[$this->heapSize]);
00149             
00150             $this->heapSize--;
00151             
00152             $this->maxHeapify($index);
00153         }
00154         
00155         private function swapElts($index1, $index2)
00156         {
00157             $tmp                    = $this->heap[$index2];
00158             $this->heap[$index2]    = $this->heap[$index1];
00159             $this->heap[$index1]    = $tmp;
00160         }
00161     }
00162 ?>