activemq-cpp-3.3.0

src/main/decaf/util/PriorityQueue.h

Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #ifndef _DECAF_UTIL_PRIORITYQUEUE_H_
00019 #define _DECAF_UTIL_PRIORITYQUEUE_H_
00020 
00021 #include <decaf/util/Config.h>
00022 #include <decaf/util/Collection.h>
00023 #include <decaf/util/AbstractQueue.h>
00024 #include <decaf/util/Iterator.h>
00025 #include <decaf/util/Comparator.h>
00026 #include <decaf/util/comparators/Less.h>
00027 
00028 #include <decaf/lang/Math.h>
00029 #include <decaf/lang/Pointer.h>
00030 #include <decaf/lang/exceptions/NullPointerException.h>
00031 #include <decaf/lang/exceptions/UnsupportedOperationException.h>
00032 
00033 #include <memory>
00034 
00035 namespace decaf {
00036 namespace util {
00037 
00068     template< typename E >
00069     class PriorityQueue : public AbstractQueue<E> {
00070     private:
00071 
00072         static const int DEFAULT_CAPACITY = 11;
00073         static const int DEFAULT_CAPACITY_RATIO = 2;
00074 
00075         int _size;
00076         int capacity;
00077         E* elements;
00078         decaf::lang::Pointer< Comparator<E> > _comparator;
00079 
00080     private:
00081 
00082         class PriorityQueueIterator : public Iterator<E> {
00083         private:
00084 
00085             PriorityQueueIterator( const PriorityQueueIterator& );
00086             PriorityQueueIterator& operator= ( const PriorityQueueIterator& );
00087 
00088         private:
00089 
00090             int position;
00091             bool allowRemove;
00092             PriorityQueue* queue;
00093 
00094         public:
00095 
00096             PriorityQueueIterator( PriorityQueue* queue ) : position( 0 ), allowRemove( false ), queue( queue ) {}
00097 
00098             virtual E next() {
00099 
00100                 if( !hasNext() ) {
00101                     throw NoSuchElementException(
00102                         __FILE__, __LINE__,
00103                         "No more elements to Iterate over." );
00104                 }
00105 
00106                 allowRemove = true;
00107                 return queue->elements[position++];
00108             }
00109 
00110             virtual bool hasNext() const {
00111                 return position < queue->_size;
00112             }
00113 
00114             virtual void remove() {
00115 
00116                 if( !allowRemove ) {
00117                     throw lang::exceptions::IllegalStateException(
00118                         __FILE__, __LINE__,
00119                         "No more elements to Iterate over." );
00120                 }
00121 
00122                 allowRemove = false;
00123                 queue->removeAt( position-- );
00124             }
00125         };
00126 
00127         class ConstPriorityQueueIterator : public PriorityQueueIterator {
00128         private:
00129 
00130             ConstPriorityQueueIterator( const ConstPriorityQueueIterator& );
00131             ConstPriorityQueueIterator& operator= ( const ConstPriorityQueueIterator& );
00132 
00133         public:
00134 
00135             ConstPriorityQueueIterator( const PriorityQueue* queue ) :
00136                 PriorityQueueIterator( const_cast<PriorityQueue*>( queue ) ) {}
00137 
00138             virtual void remove() {
00139                 throw lang::exceptions::UnsupportedOperationException(
00140                     __FILE__, __LINE__,
00141                     "PriorityQueue::Iterator::remove - Not Valid on a Const Iterator" );
00142             }
00143         };
00144 
00145         friend class PriorityQueueIterator;
00146 
00147     public:
00148 
00152         PriorityQueue() : AbstractQueue<E>(), _size( 0 ), capacity( 0 ), elements( NULL ), _comparator() {
00153             this->initQueue( DEFAULT_CAPACITY, new comparators::Less<E>() );
00154         }
00155 
00162         PriorityQueue( int initialCapacity ) :
00163             AbstractQueue<E>(), _size( 0 ), capacity( 0 ), elements( NULL ), _comparator() {
00164 
00165             this->initQueue( initialCapacity, new comparators::Less<E>() );
00166         }
00167 
00180         PriorityQueue( int initialCapacity, Comparator<E>* comparator ) :
00181             AbstractQueue<E>(), _size( 0 ), capacity( 0 ), elements( NULL ), _comparator() {
00182 
00183             if( comparator == NULL ) {
00184                 throw decaf::lang::exceptions::NullPointerException(
00185                     __FILE__, __LINE__, "Passed Comparator Cannot be NULL." );
00186             }
00187 
00188             this->initQueue( initialCapacity, comparator );
00189         }
00190 
00197         PriorityQueue( const Collection<E>& source ) :
00198             AbstractQueue<E>(), _size( 0 ), capacity( 0 ), elements( NULL ), _comparator() {
00199 
00200             this->getFromCollection( source );
00201         }
00202 
00210         PriorityQueue( const PriorityQueue<E>& source ) :
00211             AbstractQueue<E>(), _size( 0 ), capacity( 0 ), elements( NULL ), _comparator() {
00212 
00213             this->getFromPriorityQueue( source );
00214         }
00215 
00216         virtual ~PriorityQueue() {
00217             delete [] elements;
00218         }
00219 
00226         PriorityQueue<E>& operator= ( const Collection<E>& source ) {
00227             this->getFromCollection( source );
00228         }
00229 
00236         PriorityQueue<E>& operator= ( const PriorityQueue<E>& source ) {
00237             this->getFromPriorityQueue( source );
00238         }
00239 
00240     public:
00241 
00242         virtual decaf::util::Iterator<E>* iterator() {
00243             return new PriorityQueueIterator( this );
00244         }
00245 
00246         virtual decaf::util::Iterator<E>* iterator() const {
00247             return new ConstPriorityQueueIterator( this );
00248         }
00249 
00250         virtual int size() const {
00251             return this->_size;
00252         }
00253 
00254         virtual void clear() {
00255 
00256             // TODO - Provide a more efficient way to clear the array without reallocating it
00257             //        we should keep the size it grew to since if reused it could get that big
00258             //        again and reallocating all that memory could be to slow.
00259 
00260             delete [] this->elements;
00261 
00262             this->elements = new E[DEFAULT_CAPACITY];
00263             this->capacity = DEFAULT_CAPACITY;
00264             this->_size = 0;
00265         }
00266 
00267         virtual bool offer( const E& value ) {
00268 
00269             // TODO - Check for Null and throw exception
00270 
00271             increaseCapacity( _size + 1 );
00272             elements[_size++] = value;
00273             upHeap();
00274             return true;
00275         }
00276 
00277         virtual bool poll( E& result ) {
00278 
00279             if( this->isEmpty() ) {
00280                 return false;
00281             }
00282 
00283             result = elements[0];
00284             removeAt( 0 );
00285             return true;
00286         }
00287 
00288         virtual bool peek( E& result ) const {
00289 
00290             if( this->isEmpty() ) {
00291                 return false;
00292             }
00293 
00294             result = elements[0];
00295             return true;
00296         }
00297 
00298         virtual E remove() {
00299 
00300             if( !this->isEmpty() ) {
00301                 E result = elements[0];
00302                 removeAt( 0 );
00303                 return result;
00304             }
00305 
00306             throw decaf::util::NoSuchElementException(
00307                 __FILE__, __LINE__, "Unable to remove specified element from the Queue." );
00308         }
00309 
00310         virtual bool remove( const E& value ) {
00311 
00312             int targetIndex = 0;
00313             for( targetIndex = 0; targetIndex < _size; targetIndex++ ) {
00314                 if( 0 == _comparator->compare( value, elements[targetIndex] ) ) {
00315                     break;
00316                 }
00317             }
00318 
00319             if( _size == 0 || _size == targetIndex ) {
00320                 return false;
00321             }
00322 
00323             removeAt( targetIndex );
00324             return true;
00325         }
00326 
00327         virtual bool add( const E& value ) {
00328 
00329             try {
00330                 return offer( value );
00331             }
00332             DECAF_CATCH_RETHROW( lang::exceptions::UnsupportedOperationException )
00333             DECAF_CATCH_RETHROW( lang::exceptions::IllegalArgumentException )
00334             DECAF_CATCH_RETHROW( lang::exceptions::IllegalStateException )
00335             DECAF_CATCH_EXCEPTION_CONVERT( lang::exceptions::NullPointerException, lang::exceptions::UnsupportedOperationException )
00336             DECAF_CATCHALL_THROW( lang::exceptions::UnsupportedOperationException )
00337         }
00338 
00346         decaf::lang::Pointer< Comparator<E> > comparator() const {
00347             return this->_comparator;
00348         }
00349 
00350     private:
00351 
00352         void initQueue( int initialSize, Comparator<E>* comparator ) {
00353             this->elements = new E[initialSize];
00354             this->capacity = initialSize;
00355             this->_size = 0;
00356             this->_comparator.reset( comparator );
00357         }
00358 
00359         void upHeap() {
00360 
00361             int current = _size - 1;
00362             int parent = ( current - 1 ) / 2;
00363 
00364             while( current != 0 && _comparator->compare( elements[current], elements[parent] ) < 0 ) {
00365 
00366                 // swap the two
00367                 E tmp = elements[current];
00368                 elements[current] = elements[parent];
00369                 elements[parent] = tmp;
00370 
00371                 // update parent and current positions.
00372                 current = parent;
00373                 parent = ( current - 1 ) / 2;
00374             }
00375         }
00376 
00377         void downHeap( int pos ) {
00378 
00379             int current = pos;
00380             int child = 2 * current + 1;
00381 
00382             while( child < _size && !this->isEmpty() ) {
00383 
00384                 // compare the children if they exist
00385                 if( child + 1 < _size && _comparator->compare( elements[child + 1], elements[child] ) < 0 ) {
00386                     child++;
00387                 }
00388 
00389                 // compare selected child with parent
00390                 if( _comparator->compare( elements[current], elements[child] ) < 0 ) {
00391                     break;
00392                 }
00393 
00394                 // swap the two
00395                 E tmp = elements[current];
00396                 elements[current] = elements[child];
00397                 elements[child] = tmp;
00398 
00399                 // update child and current positions
00400                 current = child;
00401                 child = 2 * current + 1;
00402             }
00403         }
00404 
00405         void getFromPriorityQueue( const PriorityQueue<E>& c ) {
00406             initCapacity( c );
00407             _comparator = c.comparator();
00408             for( int ix = 0; ix < c.size(); ++ix ) {
00409                 this->elements[ix] = c.elements[ix];
00410             }
00411             _size = c.size();
00412         }
00413 
00414         void getFromCollection( const Collection<E>& c ) {
00415             initCapacity( c );
00416             _comparator.reset( new comparators::Less<E>() );
00417             std::auto_ptr< Iterator<E> > iter( c.iterator() );
00418             while( iter->hasNext() ) {
00419                 this->offer( iter->next() );
00420             }
00421         }
00422 
00423         void removeAt( int index ) {
00424             _size--;
00425             elements[index] = elements[_size];
00426             downHeap(index);
00427             elements[_size] = E();
00428         }
00429 
00430         void initCapacity( const Collection<E>& c ) {
00431 
00432             delete [] elements;
00433             _size = 0;
00434 
00435             if( c.isEmpty() ) {
00436                 capacity = 1;
00437                 elements = new E[capacity];
00438             } else {
00439                 capacity = (int) lang::Math::ceil( (double)c.size() * 1.1 );
00440                 elements = new E[capacity];
00441             }
00442         }
00443 
00444         void increaseCapacity( int size ) {
00445 
00446             if( size > capacity ) {
00447                 E* newElements = new E[ size * DEFAULT_CAPACITY_RATIO ];
00448 
00449                 for( int ix = 0; ix < capacity; ix++ ) {
00450                     newElements[ix] = elements[ix];
00451                 }
00452 
00453                 delete [] elements;
00454 
00455                 elements = newElements;
00456                 capacity = size * DEFAULT_CAPACITY_RATIO;
00457             }
00458         }
00459 
00460     };
00461 
00462 }}
00463 
00464 #endif /* _DECAF_UTIL_PRIORITYQUEUE_H_ */