00001 #ifndef MMANN_PRIORITY_QUEUE_H
00002 #define MMANN_PRIORITY_QUEUE_H
00003
00011
00012 #include "FCHelpingAlgorithms.h"
00013
00015 template <class Data>
00016 class PriorityQueueElement
00017 {
00018 public:
00020 Data* m_Item;
00021
00023 int m_Rating;
00024 };
00025
00027 template <class Data>
00028 class PriorityQueue
00029 {
00030 public:
00032 PriorityQueue(int MaxElements, int MaxRating, int GrowBy, bool IsAscending);
00033
00035 ~PriorityQueue();
00036
00041 void Push(Data* Item, int Rating);
00042
00046 Data* Pop();
00047
00051 bool IsEmpty();
00052
00053 private:
00055 int m_MaxSize;
00056
00058 int m_CurrentSize;
00059
00061 PriorityQueueElement<Data>* m_Elements;
00062
00064 int m_MaxRating;
00065
00067 int m_GrowBy;
00068
00070 bool m_IsAscendingHeap;
00071 };
00072
00073
00074
00075
00076
00078 #define PQ_PARENT_INDEX(i) ((i)>>1)
00079
00080 #define PQ_FIRST_ENTRY (1)
00081
00083 #define PQ_LEFT_CHILD_INDEX(i) ((i)<<1)
00084
00085 #define PQ_RIGHT_CHILD_INDEX(i) (((i)<<)+1)
00086
00087
00088 template <class Data>
00089 PriorityQueue<Data>::PriorityQueue(int MaxElements, int MaxRating, int GrowBy, bool IsAscending)
00090 {
00091 m_IsAscendingHeap = IsAscending;
00092 m_MaxSize = MaxElements;
00093 m_CurrentSize = 0;
00094 m_Elements = new PriorityQueueElement<Data>[m_MaxSize+1];
00095 m_GrowBy = GrowBy;
00096 m_MaxRating = MaxRating;
00097 }
00098
00099 template <class Data>
00100 PriorityQueue<Data>::~PriorityQueue()
00101 {
00102 delete [] m_Elements;
00103 }
00104
00105 template <class Data>
00106 void PriorityQueue<Data>::Push(Data* Item, int Rating)
00107 {
00108 int i;
00109
00110 if (m_CurrentSize == m_MaxSize )
00111 {
00112 int NewSize = m_MaxSize + m_GrowBy;
00113
00114 Realloc<PriorityQueueElement<Data> >(&m_Elements, m_CurrentSize+1, NewSize+1);
00115
00116 m_MaxSize = NewSize;
00117 }
00118
00119
00120
00121 i = (m_CurrentSize += 1);
00122
00123
00124
00125
00126
00127
00128
00129
00130 if(m_IsAscendingHeap)
00131 {
00132 while( ( i==PQ_FIRST_ENTRY ?
00133 (m_MaxRating)
00134 :
00135 (m_Elements[ PQ_PARENT_INDEX(i) ].m_Rating )
00136 )
00137 < Rating
00138 )
00139 {
00140 m_Elements[ i ] = m_Elements[ PQ_PARENT_INDEX(i) ];
00141
00142 i = PQ_PARENT_INDEX(i);
00143 }
00144 }
00145 else
00146 {
00147 while( ( i==PQ_FIRST_ENTRY ?
00148 (m_MaxRating)
00149 :
00150 (m_Elements[ PQ_PARENT_INDEX(i) ].m_Rating )
00151 )
00152 > Rating
00153 )
00154 {
00155 m_Elements[ i ] = m_Elements[ PQ_PARENT_INDEX(i) ];
00156
00157 i = PQ_PARENT_INDEX(i);
00158 }
00159 }
00160
00161
00162 m_Elements[i].m_Item = Item;
00163 m_Elements[i].m_Rating = Rating;
00164 }
00165
00166 template <class Data>
00167 Data* PriorityQueue<Data>::Pop()
00168 {
00169 if (IsEmpty())
00170 {
00171 return NULL;
00172 }
00173
00174 int i;
00175 int child;
00176
00177 PriorityQueueElement<Data> pMaxElement = m_Elements[PQ_FIRST_ENTRY];
00178
00179 PriorityQueueElement<Data> pLastElement = m_Elements[ m_CurrentSize-- ];
00180
00181 if(m_IsAscendingHeap)
00182 {
00183
00184
00185
00186
00187
00188 for( i=PQ_FIRST_ENTRY; PQ_LEFT_CHILD_INDEX(i) <= m_CurrentSize; i=child )
00189 {
00190
00191
00192 child = PQ_LEFT_CHILD_INDEX(i);
00193
00194 if( (child != m_CurrentSize) &&
00195 (m_Elements[child + 1].m_Rating > m_Elements[child].m_Rating) )
00196 {
00197 child ++;
00198 }
00199
00200 if( pLastElement.m_Rating < m_Elements[ child ].m_Rating )
00201 {
00202 m_Elements[ i ] = m_Elements[ child ];
00203 }
00204 else
00205 {
00206 break;
00207 }
00208 }
00209 }
00210 else
00211 {
00212
00213
00214 for( i=PQ_FIRST_ENTRY; PQ_LEFT_CHILD_INDEX(i) <= m_CurrentSize; i=child )
00215 {
00216
00217
00218 child = PQ_LEFT_CHILD_INDEX(i);
00219
00220 if( (child != m_CurrentSize) &&
00221 (m_Elements[child + 1].m_Rating < m_Elements[child].m_Rating) )
00222 {
00223 child ++;
00224 }
00225
00226 if(pLastElement.m_Rating > m_Elements[ child ].m_Rating )
00227 {
00228 m_Elements[ i ] = m_Elements[ child ];
00229 }
00230 else
00231 {
00232 break;
00233 }
00234 }
00235 }
00236
00237 m_Elements[i] = pLastElement;
00238
00239 return pMaxElement.m_Item;
00240 }
00241
00242 template <class Data>
00243 bool PriorityQueue<Data>::IsEmpty()
00244 {
00245 if( m_CurrentSize == 0 )
00246 {
00247 return true;
00248 }
00249
00250 return false;
00251 }
00252
00253 #endif