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