#include <iostream> #include <vector> #include <queue> #include <functional> class IndexMinPQ { private: std::vector<double> priorities; // 存储每个元素的优先级 std::vector<int> indices; // 存储每个元素在优先级队列中的索引 std::priority_queue<int, std::vector<int>, std::function<bool(int, int)>> pq; // 优先级队列 public: IndexMinPQ(int N) : priorities(N, std::numeric_limits<double>::infinity()), indices(N, -1) {} // 插入元素或更新元素的优先级 void insert(int index, double priority) { priorities[index] = priority; if (indices[index] != -1) { pq.erase(std::find(pq.begin(), pq.end(), indices[index])); } indices[index] = pq.size(); pq.push(index); } // 删除最小元素 int delMin() { int minIndex = pq.top(); pq.pop(); indices[minIndex] = -1; return minIndex; } // 检查队列是否为空 bool isEmpty() const { return pq.empty(); } // 获取最小元素的优先级 double getMin() const { return priorities[pq.top()]; } // 更新元素的优先级 void changePriority(int index, double newPriority) { priorities[index] = newPriority; pq.erase(std::find(pq.begin(), pq.end(), indices[index])); indices[index] = pq.size(); pq.push(index); } }; int main() { IndexMinPQ pq(10); // 创建一个容量为10的索引优先队列 pq.insert(3, 5.0); pq.insert(1, 2.0); pq.insert(5, 7.0); while (!pq.isEmpty()) { std::cout << "Minimum key: " << pq.getMin() << ", Index: " << pq.delMin() << std::endl; } return 0; }逐行解释代码
时间: 2025-04-08 22:17:56 浏览: 34
以下是对您提供的代码的逐行解释:
---
```cpp
#include <iostream>
#include <vector>
#include <queue>
#include <functional>
```
引入了必要的头文件:
- `<iostream>` 提供标准输入输出流支持。
- `<vector>` 提供动态数组功能。
- `<queue>` 提供队列相关的容器适配器。
- `<functional>` 提供函数对象的支持。
---
```cpp
class IndexMinPQ {
private:
std::vector<double> priorities; // 存储每个元素的优先级
std::vector<int> indices; // 存储每个元素在优先级队列中的索引
std::priority_queue<int, std::vector<int>, std::function<bool(int, int)>> pq; // 最小堆形式的优先级队列
```
定义了一个名为 `IndexMinPQ` 的类,用于实现带索引的最小优先队列。
私有成员包括:
- `priorities`: 保存每个索引对应的优先级值。
- `indices`: 记录某个索引是否已经在优先队列中以及它的位置信息。
- `pq`: 使用 `std::priority_queue` 实现自定义比较规则的最大堆或最小堆(这里通过第三个模板参数指定为最小堆)。
---
```cpp
public:
IndexMinPQ(int N) : priorities(N, std::numeric_limits<double>::infinity()), indices(N, -1) {}
```
构造函数初始化两个向量 `priorities` 和 `indices`:
- 将所有优先级设为无穷大 (`std::numeric_limits<double>::infinity()`) 表示初始状态下无有效数据。
- 将所有索引标记为 `-1` 表示未插入过该位置的数据。
---
```cpp
void insert(int index, double priority) {
priorities[index] = priority;
if (indices[index] != -1) {
pq.erase(std::find(pq.begin(), pq.end(), indices[index])); // 如果已存在,则先删除旧记录
}
indices[index] = pq.size(); // 设置新记录的位置索引
pq.push(index); // 向优先队列添加新的索引
}
```
`insert()` 函数的作用是将一个新的索引及其对应优先级加入到优先队列中:
1. 先更新 `priorities` 中的值。
2. 若当前索引已经存在于优先队列中,则从队列中移除原有条目(防止重复存储)。
3. 调整 `indices` 数组,并把新索引压入优先队列。
注意:这里的 `erase(find(...))` 可能效率较低,在实际应用中有更好的优化方案如基于二叉堆的手动管理等。
---
```cpp
int delMin() {
int minIndex = pq.top();
pq.pop();
indices[minIndex] = -1; // 标记此索引已被弹出不再属于队列
return minIndex;
}
```
`delMin()` 函数的功能是从优先队列中取出并返回拥有最低优先级的项:
1. 使用 `top()` 获取目前排第一的小顶堆顶部元素。
2. 执行 `pop()` 移除此元素。
3. 修改 `indices` 对应位置的状态标志位表示其已被移除。
---
```cpp
bool isEmpty() const {
return pq.empty();
}
```
检查当前优先队列是否为空,直接调用内部使用的 STL 队列方法 `empty()` 即可完成判断操作。
---
```cpp
double getMin() const {
return priorities[pq.top()];
}
```
获取当前优先队列中优先级最低的那个元素的具体数值而不需要将其真正地拿出来销毁掉。利用到了之前提到过的 `priorities[]` 这个映射表快速定位得到结果。
---
```cpp
void changePriority(int index, double newPriority) {
priorities[index] = newPriority;
pq.erase(std::find(pq.begin(), pq.end(), indices[index]));
indices[index] = pq.size();
pq.push(index);
}
```
当需要修改某一项的关键字大小时候可以调用这个变更关键字的操作。过程类似再次插入的过程只不过提前替换了原有的键值对内容然后再做相应调整确保结构正常运转下去即可!
---
### 主程序测试部分
```cpp
int main() {
IndexMinPQ pq(10); // 创建一个容量为10的索引优先队列
pq.insert(3, 5.0);
pq.insert(1, 2.0);
pq.insert(5, 7.0);
while (!pq.isEmpty()) { // 循环直到队列清空为止...
std::cout << "Minimum key: " << pq.getMin()
<< ", Index: " << pq.delMin() << std::endl;
// 输出每次找到的最小关键数及关联下标序号.
}
return 0;
}
```
主函数实例化了一个长度限制不超过十单位的对象接着往里边逐步填充值之后反复提取其中最小者打印出来直至整个序列耗尽结束运行流程。
---
**总结**: 此段 C++ 程序实现了带索引访问特性的最简版优先队列基本操作演示版本.
阅读全文
相关推荐

















