优先级队列

  1 #ifndef PRIORITYQUEUE_H
  2 #define PRIORITYQUEUE_H
  3 
  4 
  5 #include <ostream>
  6 #include <vector>
  7 #include <cassert>
  8 
  9 //----------------------- Swap -------------------------------------------
 10 //
 11 //  used to swap two values
 12 //------------------------------------------------------------------------
 13 template<class T>
 14 void Swap(T &a, T &b)
 15 {
 16   T temp = a;
 17   a = b;
 18   b = temp;
 19 }
 20 
 21 //-------------------- ReorderUpwards ------------------------------------
 22 //
 23 //  given a heap and a node in the heap, this function moves upwards
 24 //  through the heap swapping elements until the heap is ordered
 25 //------------------------------------------------------------------------
 26 template<class T>
 27 void ReorderUpwards(std::vector<T>& heap, int nd)
 28 {
 29   //move up the heap swapping the elements until the heap is ordered
 30   while ( (nd>1) && (heap[nd/2] < heap[nd]))
 31   {
 32     Swap(heap[nd/2], heap[nd]);
 33 
 34     nd /= 2;
 35   }
 36 }
 37 
 38 //--------------------- ReorderDownwards ---------------------------------
 39 //
 40 //  given a heap, the heapsize and a node in the heap, this function
 41 //  reorders the elements in a top down fashion by moving down the heap
 42 //  and swapping the current node with the greater of its two children
 43 //  (provided a child is larger than the current node)
 44 //------------------------------------------------------------------------
 45 template<class T>
 46 void ReorderDownwards(std::vector<T>& heap, int nd, int HeapSize)
 47 {
 48   //move down the heap from node nd swapping the elements until
 49   //the heap is reordered
 50   while (2*nd <= HeapSize)
 51   {
 52     int child = 2 * nd;
 53 
 54     //set child to largest of nd's two children
 55     if ( (child < HeapSize) && (heap[child] < heap[child+1]) )
 56     {
 57       ++child;
 58     }
 59 
 60     //if this nd is smaller than its child, swap
 61     if (heap[nd] < heap[child])
 62     {
 63       Swap(heap[child], heap[nd]);
 64 
 65       //move the current node down the tree
 66       nd = child;
 67     }
 68 
 69     else
 70     {
 71       break;
 72     }
 73   }
 74 }
 75 
 76 
 77 
 78 //--------------------- PriorityQ ----------------------------------------
 79 //
 80 //  basic heap based priority queue implementation
 81 //------------------------------------------------------------------------
 82 template<class T>
 83 class PriorityQ
 84 {
 85 private:
 86 
 87   std::vector<T>  m_Heap;
 88 
 89   int             m_iSize;
 90 
 91   int             m_iMaxSize;
 92 
 93   //given a heap and a node in the heap, this function moves upwards
 94   //through the heap swapping elements until the heap is ordered
 95   void ReorderUpwards(std::vector<T>& heap, int nd)
 96   {
 97     //move up the heap swapping the elements until the heap is ordered
 98     while ( (nd>1) && (heap[nd/2] < heap[nd]))
 99     {
100       Swap(heap[nd/2], heap[nd]);
101 
102       nd /= 2;
103     }
104   }
105 
106   //given a heap, the heapsize and a node in the heap, this function
107   //reorders the elements in a top down fashion by moving down the heap
108   //and swapping the current node with the greater of its two children
109   //(provided a child is larger than the current node)
110   void ReorderDownwards(std::vector<T>& heap, int nd, int HeapSize)
111   {
112     //move down the heap from node nd swapping the elements until
113     //the heap is reordered
114     while (2*nd <= HeapSize)
115     {
116      int child = 2 * nd;
117 
118       //set child to largest of nd's two children
119       if ( (child < HeapSize) && (heap[child] < heap[child+1]) )
120      {
121         ++child;
122       }
123 
124       //if this nd is smaller than its child, swap
125       if (heap[nd] < heap[child])
126       {
127         Swap(heap[child], heap[nd]);
128 
129         //move the current node down the tree
130         nd = child;
131       }
132   
133       else
134       {
135         break;
136       }
137     }
138   }
139 
140 public:
141 
142   PriorityQ(int MaxSize):m_iMaxSize(MaxSize), m_iSize(0)
143   {
144     m_Heap.assign(MaxSize+1, T());
145   }
146 
147   bool empty()const{return (m_iSize==0);}
148 
149   //to insert an item into the queue it gets added to the end of the heap
150   //and then the heap is reordered
151   void insert(const T item)
152   {
153 
154     assert (m_iSize+1 <= m_iMaxSize);
155 
156     ++m_iSize;
157 
158     m_Heap[m_iSize] = item;
159 
160     ReorderUpwards(m_Heap, m_iSize);
161   }
162 
163   //to get the max item the first element is exchanged with the lowest
164   //in the heap and then the heap is reordered from the top down. 
165   T pop()
166   {
167     Swap(m_Heap[1], m_Heap[m_iSize]);
168 
169     ReorderDownwards(m_Heap, 1, m_iSize-1);
170 
171     return m_Heap[m_iSize--];
172   }
173 
174   //so we can take a peek at the first in line
175   const T& Peek()const{return m_Heap[1];}
176 };
177 
178 //--------------------- PriorityQLow -------------------------------------
179 //
180 //  basic 2-way heap based priority queue implementation. This time the priority
181 //  is given to the lowest valued key
182 //------------------------------------------------------------------------
183 template<class T>
184 class PriorityQLow
185 {
186 private:
187 
188   std::vector<T>  m_Heap;
189 
190   int             m_iSize;
191 
192   int             m_iMaxSize;
193 
194   //given a heap and a node in the heap, this function moves upwards
195   //through the heap swapping elements until the heap is ordered
196   void ReorderUpwards(std::vector<T>& heap, int nd)
197   {
198     //move up the heap swapping the elements until the heap is ordered
199     while ( (nd>1) && (heap[nd/2] > heap[nd]))
200     {
201       Swap(heap[nd/2], heap[nd]);
202 
203       nd /= 2;
204     }
205   }
206 
207   //given a heap, the heapsize and a node in the heap, this function
208   //reorders the elements in a top down fashion by moving down the heap
209   //and swapping the current node with the smaller of its two children
210   //(provided a child is larger than the current node)
211   void ReorderDownwards(std::vector<T>& heap, int nd, int HeapSize)
212   {
213     //move down the heap from node nd swapping the elements until
214     //the heap is reordered
215     while (2*nd <= HeapSize)
216     {
217      int child = 2 * nd;
218 
219       //set child to largest of nd's two children
220       if ( (child < HeapSize) && (heap[child] > heap[child+1]) )
221      {
222         ++child;
223       }
224 
225       //if this nd is smaller than its child, swap
226       if (heap[nd] > heap[child])
227       {
228         Swap(heap[child], heap[nd]);
229 
230         //move the current node down the tree
231         nd = child;
232       }
233   
234       else
235       {
236         break;
237       }
238     }
239   }
240 
241 public:
242 
243   PriorityQLow(int MaxSize):m_iMaxSize(MaxSize), m_iSize(0)
244   {
245     m_Heap.assign(MaxSize+1, T());
246   }
247 
248   bool empty()const{return (m_iSize==0);}
249 
250   //to insert an item into the queue it gets added to the end of the heap
251   //and then the heap is reordered
252   void insert(const T item)
253   {
254     assert (m_iSize+1 <= m_iMaxSize);
255 
256     ++m_iSize;
257 
258     m_Heap[m_iSize] = item;
259 
260     ReorderUpwards(m_Heap, m_iSize);
261   }
262 
263   //to get the max item the first element is exchanged with the lowest
264   //in the heap and then the heap is reordered from the top down. 
265   T pop()
266   {
267     Swap(m_Heap[1], m_Heap[m_iSize]);
268 
269     ReorderDownwards(m_Heap, 1, m_iSize-1);
270 
271     return m_Heap[m_iSize--];
272   }
273 
274   //so we can take a peek at the first in line
275   const T& peek()const{return m_Heap[1];}
276 };
277 
278 //----------------------- IndexedPriorityQLow ---------------------------
279 //
280 //  Priority queue based on an index into a set of keys. The queue is
281 //  maintained as a 2-way heap.
282 //
283 //  The priority in this implementation is the lowest valued key
284 //------------------------------------------------------------------------
285 template<class KeyType>
286 class IndexedPriorityQLow
287 {
288 private:
289 
290   std::vector<KeyType>&  m_vecKeys;
291 
292   std::vector<int>       m_Heap;
293  
294   std::vector<int>       m_invHeap;
295 
296   int                    m_iSize,
297                          m_iMaxSize;
298 
299   void Swap(int a, int b)
300   {
301     int temp = m_Heap[a]; m_Heap[a] = m_Heap[b]; m_Heap[b] = temp;
302 
303     //change the handles too
304     m_invHeap[m_Heap[a]] = a; m_invHeap[m_Heap[b]] = b;
305   }
306 
307   void ReorderUpwards(int nd)
308   {
309     //move up the heap swapping the elements until the heap is ordered
310     while ( (nd>1) && (m_vecKeys[m_Heap[nd/2]] > m_vecKeys[m_Heap[nd]]) )
311     {      
312       Swap(nd/2, nd);
313 
314       nd /= 2;
315     }
316   }
317 
318   void ReorderDownwards(int nd, int HeapSize)
319   {
320     //move down the heap from node nd swapping the elements until
321     //the heap is reordered
322     while (2*nd <= HeapSize)
323     {
324       int child = 2 * nd;
325 
326       //set child to smaller of nd's two children
327       if ((child < HeapSize) && (m_vecKeys[m_Heap[child]] > m_vecKeys[m_Heap[child+1]]))
328       {
329         ++child;
330       }
331 
332       //if this nd is larger than its child, swap
333       if (m_vecKeys[m_Heap[nd]] > m_vecKeys[m_Heap[child]])
334       {
335         Swap(child, nd);
336 
337         //move the current node down the tree
338         nd = child;
339       }
340 
341       else
342       {
343         break;
344       }
345     }
346   }
347 
348 
349 public:
350   
351   //you must pass the constructor a reference to the std::vector the PQ
352   //will be indexing into and the maximum size of the queue.
353   IndexedPriorityQLow(std::vector<KeyType>& keys,
354                       int              MaxSize):m_vecKeys(keys),
355                                                 m_iMaxSize(MaxSize),
356                                                 m_iSize(0)
357   {
358     m_Heap.assign(MaxSize+1, 0);
359     m_invHeap.assign(MaxSize+1, 0);
360   }
361 
362   bool empty()const{return (m_iSize==0);}
363 
364   //to insert an item into the queue it gets added to the end of the heap
365   //and then the heap is reordered from the bottom up.
366   void insert(const int idx)
367   {
368     assert (m_iSize+1 <= m_iMaxSize);
369 
370     ++m_iSize;
371 
372     m_Heap[m_iSize] = idx;
373 
374     m_invHeap[idx] = m_iSize;
375 
376     ReorderUpwards(m_iSize);
377   }
378 
379   //to get the min item the first element is exchanged with the lowest
380   //in the heap and then the heap is reordered from the top down. 
381   int Pop()
382   {
383     Swap(1, m_iSize);
384 
385     ReorderDownwards(1, m_iSize-1);
386 
387     return m_Heap[m_iSize--];
388   }
389 
390   //if the value of one of the client key's changes then call this with 
391   //the key's index to adjust the queue accordingly
392   void ChangePriority(const int idx)
393   {
394     ReorderUpwards(m_invHeap[idx]);
395   }
396 };
397 
398 
399 #endif

 

posted @ 2015-03-16 15:53  David_W  阅读(197)  评论(0)    收藏  举报