关于priority_queue(优先队列)的一些误解

主要参考博客:https://blog.csdn.net/weixin_36888577/article/details/79937886

优先队列的定义:priority_queue<Type, Container, Functional>

Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆

优先队列:大顶堆->队列数据从大到小排列(也就是说根节点每次都可以找到最大的节点,俗称大顶堆)

                  小顶堆->队列数据从小到大排列(也就是说根节点每次都可以找到最小的节点,俗称小顶堆)

容易被混淆的是:优先队列定义比较方式中的Functional(仿函数)的定义 ,上代码一看就懂:
 

#include<iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;

bool cmp2(int a, int b);
int main()
{
vector<int>number = {42,17,89,37,100,95};

struct cmp  //仿函数  小顶堆
{
    bool operator()(int a , int b)
    {
        return a > b;
    }
};
priority_queue<int ,vector<int>,cmp> queue_;
for (int n : number)
{
    queue_.push(n);
}

cout << "queue_的输出: "<<endl;
while (!queue_.empty())
{
    cout << queue_.top()<<" ";
    queue_.pop();
}
cout << "  "<<endl;
cout << "number的输出: " <<endl;
sort(number.begin(),number.end(),cmp2);
for (int i = 0; i < number.size(); ++i) 
{
    cout << number[i]<<" ";
}
   return 0;
}

bool cmp2(int a, int b)  //函数不可以在main()函数里面定义
{
   return a > b;
}

函数输出:

queue_的输出:
17 37 42 89 95 100   
number的输出:
100 95 89 42 37 17

priority_queue优先队列用的 “>"大于号是小顶堆,数据从小到大输出

sort排列用的 “>"大于号是小顶堆,数据从大到小输出

下面抄了别人一段笔记,还有仿函数和函数的区别没弄明白,有时间再总结!!

//升序队列
priority_queue <int,vector<int>,greater<int> > q;
//降序队列
priority_queue <int,vector<int>,less<int> >q;

//greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)

大顶堆内容补充:

Heap 堆:平衡二叉树,最后一层从左到右紧密排列

pop()算法流程:

(1)移除根节点

(2)将最后元素移到根节点

(3)将子节点和父节点比较

(4)如果父节点比子节点小,则交换父子节点

(5)重复(3)(4)直到完成

 

#include <iostream> #include <vector> #include <queue> #include <cstring> #define int long long using namespace std; struct node { int x, y; int time; int dir; bool friend operator > (node a, node b){ return a.time > b.time; } }; const int dx[] = {0, -1, 0, 1}; const int dy[] = {1, 0, -1, 0}; signed main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int t; cin >> t; while(t --) { int n, m; cin >> n >> m; vector<vector<int>> t(n + 1, vector<int>(m + 1, 0)); vector<vector<int>> d(n + 1, vector<int>(m + 1, 0)); vector<vector<vector<int>>> dist(n + 1, vector<vector<int>>(m + 1, vector<int>(5, 0x3f3f3f3f))); vector<vector<vector<int>>> st(n + 1, vector<vector<int>>(m + 1, vector<int>(5, false))); priority_queue<node,vector<node>, greater<node>> q; for(int i = 1; i <= n; i ++) { for(int j = 1; j <= m; j ++) { cin >> t[i][j]; } } for(int i = 1; i <= n; i ++) { for(int j = 1; j <= m; j ++) { cin >> d[i][j]; } } auto dj = [&]() -> void { // 0代表向右,题目说了初始方向为向右 // 3代表向下,题目说了最后要求想下; q.push({1, 1, 0, 0}); dist[1][1][0] = 0; while(q.size()) { auto tt = q.top(); q.pop(); int x = tt.x, y = tt.y, time = tt.time, dir = tt.dir; if(st[x][y][dir]) continue; // 这个点的某个方向已经走过了 st[x][y][dir] = true; for(int i = 0; i < 4; i ++) { int nx = x + dx[i]; int ny = y + dy[i]; if(nx >= 1 && nx <= n && ny >= 1 && ny <= m) { if(st[nx][ny][i]) continue; if(dist[nx][ny][i] > dist[x][y][dir] + t[x][y] + (i != dir) * d[x][y]) { dist[nx][ny][i] = dist[x][y][dir] + t[x][y] + (i != dir) * d[x][y]; q.push({nx, ny, dist[nx][ny][i], i}); } } } } }; dj(); int res = min(min(dist[n][m][0], dist[n][m][1]), dist[n][m][2]) + d[n][m]; res = min(res, dist[n][m][3]); cout << res << '\n'; } }int n, m; struct Node{ int x, y; int time; int dir; bool operator < (const Node & t) const{ return time > t.time; // 小根堆 } }; // 右上左下 int dx[] = {0, -1, 0, 1}; int dy[] = {1, 0, -1, 0}; void solve(){ cin >> n >> m; vector<vector<int>> t(n + 1, vector<int>(m + 1, 0)); // 驶出花费时间 vector<vector<int>> d(n + 1, vector<int>(m + 1, 0)); // 转向花费时间 vector<vector<vector<int>>> dis(n + 1, vector<vector<int>>(m + 1, vector<int>(5, 1e18))); vector<vector<vector<bool>>> vis(n + 1, vector<vector<bool>>(m + 1, vector<bool>(5, false))); for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++) cin >> t[i][j]; for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++) cin >> d[i][j]; priority_queue<Node> q; // 小根堆 q.push({1, 1, 0, 0}); dis[1][1][0] = 0; while(q.size()){ auto now = q.top(); q.pop(); int x = now.x, y = now.y, time = now.time, dir = now.dir; if(vis[x][y][dir]) continue; vis[x][y][dir] = true; for(int i = 0; i < 4; i ++){ int nx = x + dx[i], ny = y + dy[i]; if(nx < 1 || nx > n || ny < 1 || ny > m) continue; if(vis[nx][ny][i]) continue; if(dis[nx][ny][i] > dis[x][y][dir] + t[x][y] + (dir != i) * d[x][y]){ dis[nx][ny][i] = dis[x][y][dir] + t[x][y] + (dir != i) * d[x][y]; q.push({nx, ny, dis[nx][ny][i], i}); } } } int res = min({dis[n][m][0], dis[n][m][1], dis[n][m][2]}) + d[n][m]; res = min(res, dis[n][m][3]); cout << res + t[n][m] << '\n'; } 这两份代码为什么输出不一样
最新发布
03-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Maccy37

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值