comparison engine/core/util/structures/priorityqueue.h @ 0:4a0efb7baf70

* Datasets becomes the new trunk and retires after that :-)
author mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222
date Sun, 29 Jun 2008 18:44:17 +0000
parents
children 90005975cdbb
comparison
equal deleted inserted replaced
-1:000000000000 0:4a0efb7baf70
1 /***************************************************************************
2 * Copyright (C) 2005-2008 by the FIFE team *
3 * http://www.fifengine.de *
4 * This file is part of FIFE. *
5 * *
6 * FIFE is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
20 ***************************************************************************/
21
22 #ifndef FIFE_SOLVER_INDEXEDPQ_H
23 #define FIFE_SOLVER_INDEXEDPQ_H
24
25 #include <cassert>
26 #include <list>
27
28 namespace FIFE {
29
30 /** A pq which stores index-value pairs for elements.
31 *
32 * This acts as a normal PQ but stores some extra information about the
33 * elements that it's storing, namely a special unique index.
34 */
35 template<typename index_type, typename priority_type>
36 class PriorityQueue {
37 public:
38 /** Used for element ordering.
39 *
40 */
41 enum Ordering {
42 Ascending, //!< lowest priority first.
43 Descending //!< highest priority first.
44 };
45
46 typedef std::pair<index_type, priority_type> value_type;
47
48 /** Constructor
49 *
50 */
51 PriorityQueue(void) : m_ordering(Ascending) {
52 }
53
54 /** Constructor
55 *
56 * @param ordering The ordering the priority queue should use.
57 */
58 PriorityQueue(const Ordering ordering) : m_ordering(ordering) {
59 }
60
61 /** Pushes a new element onto the queue.
62 *
63 * The element is pushed onto the queue and then moved up the queue until it's
64 * in the correct position by priority.
65 *
66 * @param element Of type value_type which contains both the index and the priority of the element.
67 */
68 void pushElement(const value_type& element);
69
70 /** Pops the element with the highest priority from the queue.
71 *
72 * Removes and deletes the highest priority element.
73 */
74 void popElement(void);
75
76 /** Changes the priority of an element.
77 *
78 * Locates the element with the given index and changes it's priority to the given
79 * priority, it then re-orders the priority queue to take account of this new information.
80 *
81 * @param index The index of the element to change the priority of.
82 * @param newPriority The new priority of the element.
83 * @return True if the element could be found, false otherwise.
84 */
85 bool changeElementPriority(const index_type& index, const priority_type& newPriority);
86
87 /** Removes all elements from the priority queue.
88 *
89 */
90 void clear(void);
91
92 /** Retrieves the element with the highest priority.
93 *
94 * This function will generate an assertion error if the pq is
95 * empty.
96 *
97 * @return A const reference to the highest priority element.
98 */
99 const value_type getPriorityElement(void) const {
100
101 assert(!empty());
102
103 return m_elements.front();
104
105 }
106
107 /** Determines whether the queue is currently empty.
108 *
109 * @return true if it is empty, false otherwise.
110 */
111 bool empty(void) const {
112 return m_elements.empty();
113 }
114
115 /** Returns the current size of the queue.
116 *
117 */
118 size_t size(void) const {
119 return m_elements.size();
120 }
121 private:
122 typedef std::list<value_type> ElementList;
123 typedef typename ElementList::iterator ElementListIt;
124 typedef typename ElementList::const_iterator ElementListConstIt;
125
126 //A list of valuetype pairs that represents the pq.
127 ElementList m_elements;
128
129 //The order to use when sorting the pq.
130 Ordering m_ordering;
131
132 /** Orders a PQ element up the list.
133 *
134 * @param i An iterator representing the element in the list to be sorted up.
135 */
136 void orderUp(ElementListIt i);
137 /** Orders a PQ element up the list.
138 *
139 * @param entry A const reference to a value_type which represents the element to be added to the
140 * pq.
141 */
142 void orderUp(const value_type& entry);
143
144 /** Orders a PQ element down the list.
145 *
146 * @param An iterator representing the element in the PQ to order down.
147 */
148 void orderDown(ElementListIt i);
149
150 /** Retrieves the iterator to the element with the given index.
151 *
152 * @param index A const reference to the index to find.
153 */
154 ElementListIt getElementIterator(const index_type& index) {
155
156 for(ElementListIt i = m_elements.begin(); i != m_elements.end(); ++i) {
157 if(i->first == index) {
158 return i;
159 }
160 }
161
162 return m_elements.end();
163
164 }
165
166 /** The comparison function, used to compare two elements.
167 *
168 * @param a The l-operand of the comparison operation.
169 * @param b The r-operand of the comparison operation.
170 * @return An integer representing the result of the comparison operation. 1 being a is greather than b,
171 * -1 being a is less than b and 0 meaning that they're equal.
172 */
173 int compare(const value_type& a, const value_type& b);
174 };
175 }
176
177 template<typename index_type, typename priority_type>
178 void FIFE::PriorityQueue<index_type, priority_type>::pushElement(const value_type& element) {
179 if(empty()) {
180 m_elements.push_front(element);
181 }
182 else {
183 orderUp(element);
184 }
185 }
186
187 template<typename index_type, typename priority_type>
188 void FIFE::PriorityQueue<index_type, priority_type>::popElement(void) {
189
190 if(!empty()) {
191 m_elements.pop_front();
192 }
193
194 }
195
196 template<typename index_type, typename priority_type>
197 bool FIFE::PriorityQueue<index_type, priority_type>::changeElementPriority(const index_type& index, const priority_type& newPriority) {
198
199 ElementListIt i = getElementIterator(index);
200
201 if(i == m_elements.end()) {
202 return false;
203 }
204
205 int compare_res = compare(value_type(index, newPriority), (*i));
206
207 i->second = newPriority;
208
209 if(compare_res > 0 && i != m_elements.begin()) {
210 orderDown(i);
211 } else if(compare_res < 0) {
212 orderUp(i);
213 }
214
215 return true;
216
217 }
218
219 template<typename index_type, typename priority_type>
220 void FIFE::PriorityQueue<index_type, priority_type>::clear(void) {
221
222 m_elements.clear();
223
224 }
225
226 template<typename index_type, typename priority_type>
227 void FIFE::PriorityQueue<index_type, priority_type>::orderUp(ElementListIt i) {
228
229 assert(i != m_elements.end() && L"Invalid iterator passed to function");
230
231 value_type vt = (*i);
232
233 i = m_elements.erase(i);
234
235 while(i != m_elements.end()) {
236
237 if(compare(vt, (*i)) > 0) {
238
239 m_elements.insert(i, vt);
240
241 return;
242 }
243
244 ++i;
245 }
246
247 m_elements.push_back(vt);
248
249 }
250
251 template<class index_type, class priority_type>
252 void FIFE::PriorityQueue<index_type, priority_type>::orderUp(const value_type& val)
253 {
254 for(ElementListIt i = m_elements.begin(); i != m_elements.end(); ++i)
255 {
256 assert(val.first != i->first);
257
258 if(compare(val, (*i)) > 0)
259 {
260 assert(val.first != i->first);
261
262 m_elements.insert(i, val);
263
264 return;
265 }
266 }
267
268 m_elements.push_back(val);
269 }
270
271 template<typename index_type, typename priority_type>
272 void FIFE::PriorityQueue<index_type, priority_type>::orderDown(ElementListIt i) {
273
274 assert(i != m_elements.end());
275
276 value_type vt = (*i);
277
278 i = m_elements.erase(i);
279
280 if(i == m_elements.end()) {
281 --i;
282 }
283
284 ElementListIt j = i;
285
286 ++j;
287
288 while(i != m_elements.begin()) {
289 if(compare(vt, (*i)) < 0) {
290
291 m_elements.insert(j, vt);
292
293 return;
294 }
295
296 --i;
297 --j;
298 }
299
300 m_elements.push_front(vt);
301 }
302
303 template<typename index_type, typename priority_type>
304 int FIFE::PriorityQueue<index_type, priority_type>::compare(const value_type& a, const value_type& b) {
305
306 if(m_ordering == Descending) {
307
308 if(a.second > b.second) {
309 return 1;
310 } else if(b.second > a.second) {
311 return -1;
312 }
313
314 } else {
315
316 if(a.second < b.second) {
317 return 1;
318 } else if(b.second < a.second) {
319 return -1;
320 }
321 }
322
323 return 0;
324 }
325
326 #endif