A priority queue is a data structure that maintains a set of elements, each with an associated priority. Elements are ordered by their priority, with the highest priority element at the front.
Some key properties of priority queues:
Priority queues are commonly implemented using:
Heaps are the most common because they provide fast querying and insertion.
#include <iostream>
using namespace std;
struct Node {
int data;
int priority;
Node* next;
};
class PriorityQueue {
private:
Node* head;
public:
PriorityQueue() : head(nullptr) {}
void push(int data, int priority) {
Node* newNode = createNode(data, priority);
if (head == nullptr) {
head = newNode;
}
else if (priority < head->priority) {
newNode->next = head;
head = newNode;
}
else {
Node* current = head;
while (current->next && priority >= current->next->priority) {
current = current->next;
}
newNode->next = current->next;
current->next = newNode;
}
}
int pop() {
if (isEmpty()) {
cout << "Priority Queue is empty!" << endl;
return -1;
}
Node* temp = head;
int data = temp->data;
head = head->next;
delete temp;
return data;
}
int peek() {
if (isEmpty()) {
cout << "Priority Queue is empty!" << endl;
return -1;
}
return head->data;
}
bool isEmpty() {
return head == nullptr;
}
private:
Node* createNode(int data, int priority) {
Node* newNode = new Node;
newNode->data = data;
newNode->priority = priority;
newNode->next = nullptr;
return newNode;
}
};
int main() {
PriorityQueue pq;
pq.push(4, 1);
pq.push(5, 2);
pq.push(6, 3);
pq.push(7, 0);
while (!pq.isEmpty()) {
cout << pq.peek() << " ";
pq.pop();
}
return 0;
}
Priority queues are used for:
Priority queues provide an abstract data type that can order elements by importance. This makes them very versatile for solving problems involving priority!
Methods | Time Complexity | Auxiliary Space |
---|---|---|
priority_queue::empty() | O(1) | O(1) |
priority_queue::size() | O(1) | O(1) |
priority_queue::top() | O(1) | O(1) |
priority_queue::push() | O(logN) | O(1) |
priority_queue::pop() | O(logN) | O(1) |
priority_queue::swap() | O(1) | O(N) |
priority_queue::emplace() | O(logN) | O(1) |
priority_queue value_type | O(1) | O(1) |
A min-max heap is a variant of the binary heap data structure that efficiently supports both min and max operations. It combines properties of a min-heap and a max-heap.
Min-max heaps provide efficient access to both the minimum and maximum elements in a dataset. This is useful for applications like finding extreme values or implementing priority queues with dual priorities.
we can use 2 approaches the first one is to use pointers and make each node have left and right child node. the second approach which is better IMO is to use arrays, we can make an array length n and for the parent node in cell number n store each child node in the cells
we cannot search it in a really good and efficient way like we did we binary search tree so in order to find a given number we have to look through the whole tree.
if we want to find the numbers greater than or equal to a given k we the query time is at most 3 times the number of nodes that are greater than or equal to k. why?
because for every node we return we have done a comparison operation and for its children we have done 2 operations now if we use Accounting method and charge each node that we report 3 operations we get the estimated query time.
it is possible to do it in
import heapq
def build_min_heap(arr):
n = len(arr)
# Create the heap in bottom up manner
for i in range(n//2, -1, -1):
heapify(arr, n, i)
def heapify(arr, n, i):
smallest = i
l = 2 * i + 1
r = 2 * i + 2
if l < n and arr[l] < arr[smallest]:
smallest = l
if r < n and arr[r] < arr[smallest]:
smallest = r
if smallest != i:
arr[i], arr[smallest] = arr[smallest], arr[i]
heapify(arr, n, smallest)
# Test the build heap function
nums = [5, 3, 8, 4, 1, 2]
build_min_heap(nums)
print(nums)
# [1, 2, 3, 4, 5, 8]