File indexing completed on 2025-01-19 05:21:27

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Search_Lucene
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0019  * @version    $Id$
0020  */
0021 
0022 
0023 /**
0024  * Abstract Priority Queue
0025  *
0026  * It implements a priority queue.
0027  * Please go to "Data Structures and Algorithms",
0028  * Aho, Hopcroft, and Ullman, Addison-Wesley, 1983 (corrected 1987 edition),
0029  * for implementation details.
0030  *
0031  * It provides O(log(N)) time of put/pop operations, where N is a size of queue
0032  *
0033  * @category   Zend
0034  * @package    Zend_Search_Lucene
0035  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0036  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0037  */
0038 abstract class Zend_Search_Lucene_PriorityQueue
0039 {
0040     /**
0041      * Queue heap
0042      *
0043      * Heap contains balanced partial ordered binary tree represented in array
0044      * [0] - top of the tree
0045      * [1] - first child of [0]
0046      * [2] - second child of [0]
0047      * ...
0048      * [2*n + 1] - first child of [n]
0049      * [2*n + 2] - second child of [n]
0050      *
0051      * @var array
0052      */
0053     private $_heap = array();
0054 
0055 
0056     /**
0057      * Add element to the queue
0058      *
0059      * O(log(N)) time
0060      *
0061      * @param mixed $element
0062      */
0063     public function put($element)
0064     {
0065         $nodeId   = count($this->_heap);
0066         $parentId = ($nodeId-1) >> 1;   // floor( ($nodeId-1)/2 )
0067 
0068         while ($nodeId != 0  &&  $this->_less($element, $this->_heap[$parentId])) {
0069             // Move parent node down
0070             $this->_heap[$nodeId] = $this->_heap[$parentId];
0071 
0072             // Move pointer to the next level of tree
0073             $nodeId   = $parentId;
0074             $parentId = ($nodeId-1) >> 1;   // floor( ($nodeId-1)/2 )
0075         }
0076 
0077         // Put new node into the tree
0078         $this->_heap[$nodeId] = $element;
0079     }
0080 
0081 
0082     /**
0083      * Return least element of the queue
0084      *
0085      * Constant time
0086      *
0087      * @return mixed
0088      */
0089     public function top()
0090     {
0091         if (count($this->_heap) == 0) {
0092             return null;
0093         }
0094 
0095         return $this->_heap[0];
0096     }
0097 
0098 
0099     /**
0100      * Removes and return least element of the queue
0101      *
0102      * O(log(N)) time
0103      *
0104      * @return mixed
0105      */
0106     public function pop()
0107     {
0108         if (count($this->_heap) == 0) {
0109             return null;
0110         }
0111 
0112         $top = $this->_heap[0];
0113         $lastId = count($this->_heap) - 1;
0114 
0115         /**
0116          * Find appropriate position for last node
0117          */
0118         $nodeId  = 0;     // Start from a top
0119         $childId = 1;     // First child
0120 
0121         // Choose smaller child
0122         if ($lastId > 2  &&  $this->_less($this->_heap[2], $this->_heap[1])) {
0123             $childId = 2;
0124         }
0125 
0126         while ($childId < $lastId  &&
0127                $this->_less($this->_heap[$childId], $this->_heap[$lastId])
0128           ) {
0129             // Move child node up
0130             $this->_heap[$nodeId] = $this->_heap[$childId];
0131 
0132             $nodeId  = $childId;               // Go down
0133             $childId = ($nodeId << 1) + 1;     // First child
0134 
0135             // Choose smaller child
0136             if (($childId+1) < $lastId  &&
0137                 $this->_less($this->_heap[$childId+1], $this->_heap[$childId])
0138                ) {
0139                 $childId++;
0140             }
0141         }
0142 
0143         // Move last element to the new position
0144         $this->_heap[$nodeId] = $this->_heap[$lastId];
0145         unset($this->_heap[$lastId]);
0146 
0147         return $top;
0148     }
0149 
0150 
0151     /**
0152      * Clear queue
0153      */
0154     public function clear()
0155     {
0156         $this->_heap = array();
0157     }
0158 
0159 
0160     /**
0161      * Compare elements
0162      *
0163      * Returns true, if $el1 is less than $el2; else otherwise
0164      *
0165      * @param mixed $el1
0166      * @param mixed $el2
0167      * @return boolean
0168      */
0169     abstract protected function _less($el1, $el2);
0170 }
0171