Pyrogenesis  trunk
PriorityQueue.h
Go to the documentation of this file.
1 /* Copyright (C) 2015 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef INCLUDED_PRIORITYQUEUE
19 #define INCLUDED_PRIORITYQUEUE
20 
21 /*
22  * Priority queues for pathfinder.
23  * (These probably aren't suitable for more general uses.)
24  */
25 
26 #ifdef NDEBUG
27 #define PRIORITYQUEUE_DEBUG 0
28 #else
29 #define PRIORITYQUEUE_DEBUG 1
30 #endif
31 
32 template <typename Item, typename CMP>
34 {
35  bool operator()(const Item& a, const Item& b) const
36  {
37  if (CMP()(b.rank, a.rank)) // higher costs are lower priority
38  return true;
39  if (CMP()(a.rank, b.rank))
40  return false;
41  // Need to tie-break to get a consistent ordering
42  if (CMP()(b.h, a.h)) // higher heuristic costs are lower priority
43  return true;
44  if (CMP()(a.h, b.h))
45  return false;
46  if (a.id < b.id)
47  return true;
48  if (b.id < a.id)
49  return false;
50 #if PRIORITYQUEUE_DEBUG
51  debug_warn(L"duplicate tiles in queue");
52 #endif
53  return false;
54  }
55 };
56 
57 
58 /**
59  * Priority queue implemented as a binary heap.
60  * This is quite dreadfully slow in MSVC's debug STL implementation,
61  * so we shouldn't use it unless we reimplement the heap functions more efficiently.
62  */
63 template <typename ID, typename R, typename H, typename CMP = std::less<R> >
65 {
66 public:
67  struct Item
68  {
69  ID id;
70  R rank; // f = g+h (estimated total cost of path through here)
71  H h; // heuristic cost
72  };
73 
74  void push(const Item& item)
75  {
76  m_Heap.push_back(item);
77  push_heap(m_Heap.begin(), m_Heap.end(), QueueItemPriority<Item, CMP>());
78  }
79 
80  void promote(ID id, R UNUSED(oldrank), R newrank, H newh)
81  {
82  // Loop backwards since it seems a little faster in practice
83  for (ssize_t n = m_Heap.size() - 1; n >= 0; --n)
84  {
85  if (m_Heap[n].id == id)
86  {
87 #if PRIORITYQUEUE_DEBUG
88  ENSURE(m_Heap[n].rank > newrank);
89 #endif
90  m_Heap[n].rank = newrank;
91  m_Heap[n].h = newh;
92  push_heap(m_Heap.begin(), m_Heap.begin()+n+1, QueueItemPriority<Item, CMP>());
93  return;
94  }
95  }
96  }
97 
98  Item pop()
99  {
100 #if PRIORITYQUEUE_DEBUG
101  ENSURE(m_Heap.size());
102 #endif
103  Item r = m_Heap[0];
104  pop_heap(m_Heap.begin(), m_Heap.end(), QueueItemPriority<Item, CMP>());
105  m_Heap.pop_back();
106  return r;
107  }
108 
109  bool empty()
110  {
111  return m_Heap.empty();
112  }
113 
114  size_t size()
115  {
116  return m_Heap.size();
117  }
118 
119  void clear()
120  {
121  m_Heap.clear();
122  }
123 
124  std::vector<Item> m_Heap;
125 };
126 
127 /**
128  * Priority queue implemented as an unsorted array.
129  * This means pop() is O(n), but push and promote are O(1), and n is typically small
130  * (average around 50-100 in some rough tests).
131  * It seems fractionally slower than a binary heap in optimised builds, but is
132  * much simpler and less susceptible to MSVC's painfully slow debug STL.
133  */
134 template <typename ID, typename R, typename H, typename CMP = std::less<R> >
136 {
137 public:
138  struct Item
139  {
140  ID id;
141  R rank; // f = g+h (estimated total cost of path through here)
142  H h; // heuristic cost
143  };
144 
145  void push(const Item& item)
146  {
147  m_List.push_back(item);
148  }
149 
150  Item* find(ID id)
151  {
152  for (size_t n = 0; n < m_List.size(); ++n)
153  {
154  if (m_List[n].id == id)
155  return &m_List[n];
156  }
157  return NULL;
158  }
159 
160  void promote(ID id, R UNUSED(oldrank), R newrank, H newh)
161  {
162  find(id)->rank = newrank;
163  find(id)->h = newh;
164  }
165 
167  {
168 #if PRIORITYQUEUE_DEBUG
169  ENSURE(m_List.size());
170 #endif
171  // Loop backwards looking for the best (it's most likely to be one
172  // we've recently pushed, so going backwards saves a bit of copying)
173  Item best = m_List.back();
174  size_t bestidx = m_List.size()-1;
175  for (ssize_t i = (ssize_t)bestidx-1; i >= 0; --i)
176  {
177  if (QueueItemPriority<Item, CMP>()(best, m_List[i]))
178  {
179  bestidx = i;
180  best = m_List[i];
181  }
182  }
183  // Swap the matched element with the last in the list, then pop the new last
184  m_List[bestidx] = m_List[m_List.size()-1];
185  m_List.pop_back();
186  return best;
187  }
188 
189  bool empty()
190  {
191  return m_List.empty();
192  }
193 
194  size_t size()
195  {
196  return m_List.size();
197  }
198 
199 
200  void clear()
201  {
202  m_List.clear();
203  }
204 
205  std::vector<Item> m_List;
206 };
207 
208 #endif // INCLUDED_PRIORITYQUEUE
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
Definition: code_annotation.h:38
H h
Definition: PriorityQueue.h:142
std::vector< Item > m_List
Definition: PriorityQueue.h:205
bool empty()
Definition: PriorityQueue.h:189
void clear()
Definition: PriorityQueue.h:200
void push(const Item &item)
Definition: PriorityQueue.h:145
Priority queue implemented as a binary heap.
Definition: PriorityQueue.h:64
#define R(t)
Definition: PriorityQueue.h:138
ID id
Definition: PriorityQueue.h:69
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
Definition: debug.h:287
size_t size()
Definition: PriorityQueue.h:194
void push(const Item &item)
Definition: PriorityQueue.h:74
bool empty()
Definition: PriorityQueue.h:109
R rank
Definition: PriorityQueue.h:141
Definition: PriorityQueue.h:33
bool operator()(const Item &a, const Item &b) const
Definition: PriorityQueue.h:35
R rank
Definition: PriorityQueue.h:70
intptr_t ssize_t
Definition: wposix_types.h:82
Priority queue implemented as an unsorted array.
Definition: PriorityQueue.h:135
Item * find(ID id)
Definition: PriorityQueue.h:150
size_t size()
Definition: PriorityQueue.h:114
Item pop()
Definition: PriorityQueue.h:98
H h
Definition: PriorityQueue.h:71
void promote(ID id, R oldrank, R newrank, H newh)
Definition: PriorityQueue.h:80
#define debug_warn(expr)
display the error dialog with the given text.
Definition: debug.h:329
Definition: PriorityQueue.h:67
std::vector< Item > m_Heap
Definition: PriorityQueue.h:124
void promote(ID id, R oldrank, R newrank, H newh)
Definition: PriorityQueue.h:160
ID id
Definition: PriorityQueue.h:140
#define CMP(f)
Item pop()
Definition: PriorityQueue.h:166
void clear()
Definition: PriorityQueue.h:119