📅  最后修改于: 2023-12-03 15:40:16.313000             🧑  作者: Mango
最小堆优先级队列是一种非常常见的数据结构,它可以在 $O(logn)$ 的时间内实现 push 和 pop 操作。在 C++ 中,STL 的 priority_queue 就是基于最大堆实现的优先级队列,而最小堆优先级队列则需要手动实现。
最小堆是一种二叉树数据结构,它的每个节点的父节点都要小于或等于它的子节点。可以使用数组来实现最小堆,我们假设数组下标是从 1 开始的,那么节点 i 的左子节点就是 $2i$,右子节点就是 $2i+1$,父节点就是 $\lfloor i/2 \rfloor$。
现在来看一下如何实现一个最小堆。在 C++ 中,我们可以使用一个 vector 数组来存储堆中的元素。由于 vector 的下标从 0 开始,所以可以使用一个小技巧,将堆中的元素下标从 1 开始,而 0 号位置留空。这样就可以直接使用公式计算节点的左右子节点和父节点了。
class MinHeap {
public:
MinHeap() {}
// 向堆中插入一个元素
void push(int val) {
heap.push_back(val);
int cur = size();
while (cur > 1) {
int parent = cur / 2;
if (heap[parent] > heap[cur]) {
swap(heap[parent], heap[cur]);
cur = parent;
} else {
break;
}
}
}
// 从堆中取出并删除最小元素
int pop() {
int res = heap[1];
heap[1] = heap.back();
heap.pop_back();
int cur = 1;
while (cur * 2 < size()) {
int child = cur * 2;
if (child + 1 < size() && heap[child + 1] < heap[child]) {
child++;
}
if (heap[child] < heap[cur]) {
swap(heap[cur], heap[child]);
cur = child;
} else {
break;
}
}
return res;
}
// 获取堆中最小元素
int top() const {
return heap[1];
}
// 判断堆是否为空
bool empty() const {
return size() == 0;
}
// 获取堆的大小
int size() const {
return heap.size() - 1;
}
private:
vector<int> heap;
};
以上就是最小堆的实现代码,可以通过 push、pop、top、empty 和 size 函数来操作最小堆。
有了最小堆,我们就可以通过它来实现最小堆优先级队列。最小堆优先级队列可以使用两个堆来实现,一个是存储元素的堆,另一个是存储元素的优先级的堆。其中,第一个堆按照元素大小排序,第二个堆按照元素的优先级排序,排序方式和最小堆相反,即优先级最大的元素排在堆顶。
下面是最小堆优先级队列的实现代码:
struct Node {
int val; // 元素值
int priority; // 优先级
Node(int val, int priority) : val(val), priority(priority) {}
bool operator<(const Node& other) const {
return priority > other.priority;
}
};
class MinHeapPriorityQueue {
public:
MinHeapPriorityQueue() {}
// 向队列中插入一个元素
void push(int val, int priority) {
heap.push(Node(val, priority));
}
// 从队列中取出并删除优先级最高的元素
int pop() {
int res = heap.top().val;
heap.pop();
return res;
}
// 判断队列是否为空
bool empty() const {
return heap.empty();
}
private:
priority_queue<Node> heap; // 存放元素的优先级堆
};
最小堆优先级队列是一种非常实用的数据结构,它可以帮助我们在处理一些需要按照优先级排序的元素时,快速地取出优先级最高的元素。在 C++ 中,STL 的 priority_queue 是最大堆优先级队列,我们可以通过手动实现最小堆来实现最小堆优先级队列。