Data Structure 8 - priority queue
Definition
A priority queue is an abstract data type which is like a regular queue or stack data structure, but where additionally each element has a “priority” associated with it.
In a priority queue, an element with high priority is served or dequeued before an element with low priority.
If two elements have the same priority, they are served according to the order in which they were enqueued, while in other implementations, ordering of elements with the same priority is undefined.
While priority queues are often implemented with heaps, they are conceptually distinct from heaps.
A priority queue is a concept like “a list” or “a map”, just as a list can be implemented with a linked list or an array.
A priority queue can be implemented with a heap or a variety of other methods such as an unordered array.
Implementation
Naive
TO(n) for popping
class PriorityQueue():
def __init__(self):
self.queue=[]
def isEmpty(Self):
return not self.queue
def append(self,x):
self.queue.append(x)
#popping the element based on Priority
def pop(self):
max_idx=0
for i in range(len(self.queue)):
if self.queue[i]>self.queue[max_idx]:
max_idx=i
pop=self.queue[max_idx]
del self.queue[max_idx]
return pop
pq=PriorityQueue()
pq.append(12)
pq.append(4)
pq.append(14)
pq.append(7)
while not pq.isEmpty():
print(pq.pop())
Output:
14
12
7
4
Binary Heap
see heap #definition
Python heapq
Problems
leetcode 218 - The Skyline Problem [H]
Given the locations and height of all the buildings, write a program to output the skyline formed by these buildings collectively.
Example:
Input: [left,right,height]
[[1,3,3],[2,4,4],[5,8,2],[6,7,4],[8,9,4]]
Output: [[1,3],[2,4],[4,0],[5,2],[6,4],[7,2],[8,4],[9,0]]
5 |
4 | |-----| |--| |--|
3 | |--|--| | | | | |
2 | | | | | |--|--|--| |
1 | | | | | | | | | |
------------------------------
0 1 2 3 4 5 6 7 8 9
5 |
4 | x-----| x--| x--|
3 | x--|--| | | | | |
2 | | | | | x--|--x--| |
1 | | | | | | | | | |
------------x--------------x--
0 1 2 3 4 5 6 7 8 9
Solution - use max heap:
- transfer [l,r,h] to [l,-h,r]+[r,h,None]
Note 1: -h for discriminating the left and the right edges
Note 2: for the left to be sorted ahead of the right
Note 3: minus value of height suits for the default minheap setting - sort the new rectangles of [l,-h,r]+[r,h,None]
- use a min heap (default) to record height and right (h,r)
- when meets left edge (h<0), heap push (h,r)
- when not left edge and current left (which was the right edge originally) is larger than the recorded right, which means the previous whole block reaches right end, heap pop all the recorded (h,r)
-
every time when earlier top!=new heap[0][0], which is the latest max height, res append [l,-heap[0][0]]
Note 1: always append left edge points
Note 2: heap[0][0] is always the highest right edges, cuz of the property of default minheap from heapql,r,h [1,3,3] [2,4,4] [5,8,2] [6,7,4] [8,9,4] -> sorted([l,-h,r]+[r,h,None]) [1,-3,3] [2,-4,4] [3,3,N] [4,4,N] [5,-2,8] [6,-4,7] [7,4,N] [8,-4,9] [8,2,N] [9,4,N] heap ('leftpush', [(-3, 3), (0, inf)]) ('leftpush', [(-4, 4), (0, inf), (-3, 3)]) ('whilepop', [(-3, 3), (0, inf)]) ('whilepop', [(0, inf)]) ('leftpush', [(-2, 8), (0, inf)]) ('leftpush', [(-4, 7), (0, inf), (-2, 8)]) ('whilepop', [(-2, 8), (0, inf)]) ('whilepop', [(0, inf)]) ('leftpush', [(-4, 9), (0, inf)]) ('whilepop', [(0, inf)])
import heapq
class Solution():
def getSkyline(self,buildings):
rect=[[l,-h,r] for l,r,h in buildings]+[[r,h,None] for l,r,h in buildings]
rect.sort()
res=[]
heap=[(0,float('inf'))] #store (h,r)
for l,h,r in rect:
top=heap[0][0]
while l>=heap[0][1]: #left >= most right, jump to next new block
heapq.heappop(heap) #pop all
if h<0:
heapq.heappush(heap,(h,r))
if top!=heap[0][0]:
res.append([l,-heap[0][0]])
return res