C++ 优先级队列(运用绑定器实现大小根堆)
1. 概要
在C++的优先级队列priority_queue中,其实是使用大小根堆实现的(默认是大根堆)。
在这里,我们使用了函数绑定器functional绑定了一根函数对象来自定义的实现大小根堆。
另外,对于实现一个大小根堆,有两个重要的操作需要考虑:
- 入堆操作
- 出堆操作
1. 1 入堆操作
对于入堆,一开始其实把入堆的元素放到数组的最后面。放在最后的这个元素在二叉树里面相当于就在叶子结点中。
但是,对于大根堆来说,每个节点的父节点是需要大于它的孩子节点的。刚插入的、放在叶子节点中的这个节点可能比它的夫节点还要大,因此需要进行上浮操作。
1. 2 出堆操作
对于出堆,首先需要记录数组的第一个元素(相当于堆顶元素)的值,然后用最后一个值覆盖第一个元素。再把最后一个元素给pop掉。
这时新的堆顶元素不一定能符合父节点大于两个孩子节点的条件,因此需要进行下沉操作。
2. 代码实现
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <assert.h>
#include <time.h>
using namespace std;
class priorityQueue {
public:
using Cmp = function<bool(int, int)>;
priorityQueue(Cmp cmp = greater<int>()) : cmp_(cmp) {}
void push(int val) {
if (this->empty()) {
src_.push_back(val);
} else {
src_.push_back(val);
siftUp();
}
}
void pop() {
assert(!this->empty());
if (src_.size() == 1) {
src_.pop_back();
} else {
swap(src_[0], src_[this->size() - 1]);
src_.pop_back();
siftDown();
}
}
int top() {
assert(!this->empty());
return src_.front();
}
bool empty() {
return src_.size() == 0;
}
int size() {
return src_.size();
}
private:
// 上浮操作
void siftUp() {
int i = src_.size() - 1;
while (i > 0) {
int fatherIndex = (i - 1) / 2;
// 当前结点大于父节点
if (cmp_(src_[i], src_[fatherIndex])) {
swap(src_[i], src_[fatherIndex]);
i = fatherIndex;
} else {
break;
}
}
}
// 下沉操作
void siftDown() {
int i = 0;
while (i < src_.size() / 2) {
int lson = i * 2 + 1;
int rson = i * 2 + 2;
int largestIndex = i;
if (lson < src_.size() && cmp_(src_[lson], src_[largestIndex])) {
largestIndex = lson;
}
if (rson < src_.size() && cmp_(src_[rson], src_[largestIndex])) {
largestIndex = rson;
}
if (i != largestIndex) {
swap(src_[i], src_[largestIndex]);
i = largestIndex;
} else {
break;
}
}
}
private:
vector<int> src_;
Cmp cmp_;
};
int main() {
priorityQueue maxHeap;
srand(time(nullptr));
int size = 20;
for (int i = 0; i < size; ++i) {
int val = rand() % 100;
maxHeap.push(val);
}
while (!maxHeap.empty()) {
int val = maxHeap.top();
cout << val << " ";
maxHeap.pop();
}
return 0;
}

本文介绍了如何在C++中利用函数绑定器实现自定义大小根堆的优先级队列。通过详细讲解入堆和出堆操作,以及提供完整的代码实现,展示了如何维护大根堆的性质并进行元素的添加与删除。示例代码中展示了如何使用`std::function`和`std::greater`来定制比较函数,实现一个最小堆。
1874

被折叠的 条评论
为什么被折叠?



