|
3 | 3 | from copy import deepcopy as dc
|
4 | 4 |
|
5 | 5 | __all__ = [
|
6 |
| - 'Queue' |
| 6 | + 'Queue', |
| 7 | + 'PriorityQueue' |
7 | 8 | ]
|
8 | 9 |
|
9 | 10 | class Queue(object):
|
@@ -171,3 +172,97 @@ def __len__(self):
|
171 | 172 |
|
172 | 173 | def __str__(self):
|
173 | 174 | return str(self.queue)
|
| 175 | + |
| 176 | +class PriorityQueue(object): |
| 177 | + """ |
| 178 | + Represents the concept of priority queue. |
| 179 | +
|
| 180 | + Parameters |
| 181 | + ========== |
| 182 | +
|
| 183 | + implementation: str |
| 184 | + The implementation which is to be |
| 185 | + used for supporting operations |
| 186 | + of priority queue. |
| 187 | + The following implementations are supported, |
| 188 | + 'linked_list' -> Linked list implementation. |
| 189 | + Optional, by default, 'linked_list' implementation |
| 190 | + is used. |
| 191 | + comp: function |
| 192 | + The comparator to be used while comparing priorities. |
| 193 | + Must return a bool object. |
| 194 | + By default, `lambda u, v: u > v` is used to compare |
| 195 | + priorities i.e., maximum priority elements are extracted |
| 196 | + by pop operation. |
| 197 | +
|
| 198 | + Examples |
| 199 | + ======== |
| 200 | +
|
| 201 | + >>> from pydatastructs import PriorityQueue |
| 202 | + >>> pq = PriorityQueue() |
| 203 | + >>> pq.push(1, 2) |
| 204 | + >>> pq.push(2, 3) |
| 205 | + >>> pq.pop() |
| 206 | + 2 |
| 207 | + >>> pq2 = PriorityQueue(comp=lambda u, v: u < v) |
| 208 | + >>> pq2.push(1, 2) |
| 209 | + >>> pq2.push(2, 3) |
| 210 | + >>> pq2.pop() |
| 211 | + 1 |
| 212 | +
|
| 213 | + References |
| 214 | + ========== |
| 215 | +
|
| 216 | + .. [1] https://en.wikipedia.org/wiki/Priority_queue#Naive_implementations |
| 217 | + """ |
| 218 | + |
| 219 | + def __new__(cls, implementation='linked_list', **kwargs): |
| 220 | + if implementation == 'linked_list': |
| 221 | + return LinkedListPriorityQueue( |
| 222 | + kwargs.get("comp", lambda u, v: u > v) |
| 223 | + ) |
| 224 | + |
| 225 | + def push(self, value, priority): |
| 226 | + raise NotImplementedError( |
| 227 | + "This is an abstract method.") |
| 228 | + |
| 229 | + def pop(self): |
| 230 | + raise NotImplementedError( |
| 231 | + "This is an abstract method.") |
| 232 | + |
| 233 | + @property |
| 234 | + def is_empty(self): |
| 235 | + raise NotImplementedError( |
| 236 | + "This is an abstract method.") |
| 237 | + |
| 238 | +class LinkedListPriorityQueue(PriorityQueue): |
| 239 | + |
| 240 | + __slots__ = ['items', 'comp'] |
| 241 | + |
| 242 | + def __new__(cls, comp=lambda u, v: u > v): |
| 243 | + obj = object.__new__(cls) |
| 244 | + obj.items = SinglyLinkedList() |
| 245 | + obj.comp = comp |
| 246 | + return obj |
| 247 | + |
| 248 | + def push(self, value, priority): |
| 249 | + self.items.append(value, priority) |
| 250 | + |
| 251 | + def pop(self): |
| 252 | + if self.is_empty: |
| 253 | + raise IndexError("Priority queue is empty.") |
| 254 | + |
| 255 | + walk = self.items.head |
| 256 | + i, max_i, max_p = 0, 0, walk.data |
| 257 | + while walk is not None: |
| 258 | + if self.comp(walk.data, max_p): |
| 259 | + max_i = i |
| 260 | + max_p = walk.data |
| 261 | + i += 1 |
| 262 | + walk = walk.next |
| 263 | + pop_val = self.items.extract(max_i) |
| 264 | + return pop_val.key |
| 265 | + |
| 266 | + @property |
| 267 | + def is_empty(self): |
| 268 | + return self.items.size == 0 |
0 commit comments