CLucene - a full-featured, c++ search engine
API Documentation
00001 /*------------------------------------------------------------------------------ 00002 * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team 00003 * 00004 * Distributable under the terms of either the Apache License (Version 2.0) or 00005 * the GNU Lesser General Public License, as specified in the COPYING file. 00006 ------------------------------------------------------------------------------*/ 00007 #ifndef _lucene_util_PriorityQueue_ 00008 #define _lucene_util_PriorityQueue_ 00009 00010 CL_NS_DEF(util) 00011 00012 00015 template <class _type,typename _valueDeletor> class PriorityQueue:LUCENE_BASE { 00016 private: 00017 size_t _size; 00018 bool dk; 00019 size_t maxSize; 00020 protected: 00021 _type* heap; //(was object[]) 00022 00023 private: 00024 void upHeap(){ 00025 size_t i = _size; 00026 _type node = heap[i]; // save bottom node (WAS object) 00027 int32_t j = ((uint32_t)i) >> 1; 00028 while (j > 0 && lessThan(node,heap[j])) { 00029 heap[i] = heap[j]; // shift parents down 00030 i = j; 00031 j = ((uint32_t)j) >> 1; 00032 } 00033 heap[i] = node; // install saved node 00034 } 00035 void downHeap(){ 00036 size_t i = 1; 00037 _type node = heap[i]; // save top node 00038 size_t j = i << 1; // find smaller child 00039 size_t k = j + 1; 00040 if (k <= _size && lessThan(heap[k], heap[j])) { 00041 j = k; 00042 } 00043 while (j <= _size && lessThan(heap[j],node)) { 00044 heap[i] = heap[j]; // shift up child 00045 i = j; 00046 j = i << 1; 00047 k = j + 1; 00048 if (k <= _size && lessThan(heap[k], heap[j])) { 00049 j = k; 00050 } 00051 } 00052 heap[i] = node; // install saved node 00053 } 00054 00055 protected: 00056 PriorityQueue(){ 00057 this->_size = 0; 00058 this->dk = false; 00059 this->heap = NULL; 00060 this->maxSize = 0; 00061 } 00062 00063 // Determines the ordering of objects in this priority queue. Subclasses 00064 // must define this one method. 00065 virtual bool lessThan(_type a, _type b)=0; 00066 00067 // Subclass constructors must call this. 00068 void initialize(const int32_t maxSize, bool deleteOnClear){ 00069 _size = 0; 00070 dk = deleteOnClear; 00071 int32_t heapSize; 00072 if (0 == maxSize) 00073 // We allocate 1 extra to avoid if statement in top() 00074 heapSize = 2; 00075 else 00076 heapSize = maxSize + 1; 00077 heap = _CL_NEWARRAY(_type,heapSize); 00078 this->maxSize = maxSize; 00079 } 00080 00081 public: 00082 virtual ~PriorityQueue(){ 00083 clear(); 00084 _CLDELETE_ARRAY(heap); 00085 } 00086 00092 void put(_type element){ 00093 if ( _size>=maxSize ) 00094 _CLTHROWA(CL_ERR_IndexOutOfBounds,"add is out of bounds"); 00095 00096 ++_size; 00097 heap[_size] = element; 00098 upHeap(); 00099 } 00100 00107 bool insert(_type element){ 00108 _type t = insertWithOverflow(element); 00109 if (t != element) { 00110 if (t) _valueDeletor::doDelete(t); 00111 return true; 00112 } 00113 return false; 00114 } 00115 00128 _type insertWithOverflow(_type element) { 00129 if(_size < maxSize){ 00130 put(element); 00131 return NULL; 00132 }else if(_size > 0 && !lessThan(element, heap[1])){ 00133 _type ret = heap[1]; 00134 heap[1] = element; 00135 adjustTop(); 00136 return ret; 00137 }else 00138 return element; 00139 } 00140 00144 _type top(){ 00145 // We don't need to check size here: if maxSize is 0, 00146 // then heap is length 2 array with both entries null. 00147 // If size is 0 then heap[1] is already null. 00148 return heap[1]; 00149 } 00150 00154 _type pop(){ 00155 if (_size > 0) { 00156 _type result = heap[1]; // save first value 00157 heap[1] = heap[_size]; // move last to first 00158 00159 heap[_size] = (_type)0; // permit GC of objects 00160 --_size; 00161 downHeap(); // adjust heap 00162 return result; 00163 } else 00164 return (_type)NULL; 00165 } 00166 00174 void adjustTop(){ 00175 downHeap(); 00176 } 00177 00178 00182 size_t size(){ 00183 return _size; 00184 } 00185 00189 void clear(){ 00190 for (size_t i = 1; i <= _size; ++i){ 00191 if ( dk ){ 00192 _valueDeletor::doDelete(heap[i]); 00193 } 00194 } 00195 _size = 0; 00196 } 00197 }; 00198 00199 CL_NS_END 00200 #endif