c++ STL 优先队列

  • Post author:
  • Post category:其他


前言:建议初学者跟着把每一个样例打一遍,并自己改变代码做到更多不同的效果。

优先队列是什么,干嘛用的

优先队列,即带有优先级的队列。不懂啥是队列的可以先去学队列了(先进先出的就是队列)。那么带有优先级,就是可以做到排序的队列,比如我依次放入2,1,3,小顶堆优先队列就可以通过1,2,3的顺序把他们吐出来。而一般的队列只能以2,1,3的顺序把他们吐出来。


作用:

以最短路和BFS为例,就经常使用优先队列。当然其他问题和算法也经常使用优先队列。

要学些什么

学习优先队列的基础用法前,你可以啥也没学,只会用法就行。但是要想知道优先队列的原理,实现优先队列的自定义,建议至少把二叉树,堆排序给学了,最好把C++的类也学了。这里不会讲优先队列的原理,而是注重使用方法。这东西学会怎么用比学会原理的时间要早太多了。

如果代码看着眼花,那就跟着打一次,边打边尝试理解它的意思。



一定要上手实践


优先队列的定义:

priority_queue<Type, Container, Functional>


Type

是数据类型;

Container

是容器类型,一般使用vector;

Functional

是比较的方式。

优先队列的基本操作:

  • top 访问队头元素

  • empty 队列是否为空

  • size 返回队列内元素个数

  • push 插入元素到队尾并排序

  • emplace 原地构造一个元素并插入队列

  • pop 弹出队头元素

  • swap 交换内容


基础使用

学会使用这部分前你不需要懂它到底啥原理。

注:

大顶堆:字面意思,根(顶)最大的堆。

小顶堆:根(顶)最小的堆。

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

//_________________默认为大顶堆_________________
priority_queue<int> q1;


//_________________标准一般写法_________________
//小顶堆
priority_queue<int,vector<int>,greater<int> > q2;
//大顶堆
priority_queue<int,vector<int>,less<int> >q3;
priority_queue<string,vector<string>, greater<string> >q4;

int main()
{
    //测试样例1,默认情况
    q1.push(2);
    q1.push(1);
    q1.push(4);
    cout<<"q1:";
    while(!q1.empty()){
        cout<<q1.top()<<" ";
        q1.pop();
    }
    cout<<endl;

    //测试样例2,小顶堆
    q2.push(3);
    q2.push(2);
    q2.push(1);
    cout<<"q2:";
    while(!q2.empty()){
        cout<<q2.top()<<" ";
        q2.pop();
    }
    cout<<endl;
    
    //测试样例3:大顶堆
    q3.push(1);
    q3.push(2);
    q3.push(3);
    cout<<"q3:";
    while(!q3.empty()){
        cout<<q3.top()<<" ";
        q3.pop();
    }
    cout<<endl;

    //测试样例4:字符串形式
    q4.push("hello");
    q4.push("issey");
    q4.push("abc");
    q4.push("cccf");
    cout<<"q4:";
    while(!q4.empty()){
        cout<<q4.top()<<" ";
        q4.pop();
    }
    cout<<endl;

    return 0;
}

进阶使用

在学习这部分前,你可以不学前置知识,但顶多只能照猫画虎,建议现学上面提到的前置知识,再来学就很好懂了。

进阶1:pair

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

//_____________piar_________________
//标准写法
priority_queue<pair<int,string>,vector<pair<int,string> >,greater<pair<int,string> > >q1;
//当然也可以简写,不过默认大顶堆
priority_queue<pair<int,int> >q2;

int main()
{
    //测试样例1:
    pair<int,string> a(1,"issey");
    pair<int,string> b(1,"aaa");
    pair<int,string> c(2,"zz");
    q1.push(a);
    q1.push(b);
    q1.push(c);
    cout<<"q1:"<<endl;
    while(!q1.empty()){
        cout<<q1.top().first<<" ";
        cout<<q1.top().second<<endl;
        q1.pop();
    }

    //测试样例2:
    pair<int,int> A(1,1);
    pair<int,int> B(1,2);
    pair<int,int> C(2,0);
    q2.push(A);
    q2.push(B);
    q2.push(C);
    cout<<"q2:"<<endl;
    while(!q2.empty()){
        cout<<q2.top().first<<" ";
        cout<<q2.top().second<<endl;
        q2.pop();
    }
    return 0;
}

进阶2:自定义优先队列

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

//__________方法1:在结构体里重载运算符________
typedef struct Node{
    int sum,id;
    friend bool operator<(Node a,Node b){
        return a.sum>b.sum;//通过属性sum建立小顶堆
    }
}Node;
priority_queue<Node> q1;
/*
    关于结构体重载运算符和优先队列定义的解释:
        priority_queue<Node> q1是默认定义方式,我们知道默认的应该是大顶堆,堆排序构建大顶
    堆时,应该是当前节点小于(左、右)孩子,才进行交换,所以默认的运算符是'<',所以在结构体
    重载运算符时,应该是friend bool operator<(Node a,Node b)。
        而我们想实现通过sum建立小顶堆,所以重载'<'时,把真正的比较对象置为'>','>'是构建小顶
    堆,所以使用默认方式建立优先队列,本来要读'<',实际上读的是'>',就简化了书写。(笑,这种方
    法太坏蛋了)
*/


//_________________方法2:重写仿函数__________________
typedef struct Node2{
    int id,sum;
}Node2;

struct cmp{
    bool operator()(const Node2 a,const Node2 b){
        return a.sum<b.sum;//通过sum构建大顶堆
    }
};
priority_queue<Node2,vector<Node2>,cmp >q2;


int main()
{
    //测试样例1
    Node a,b,c;
    a.id = 1;a.sum = 10;
    b.id = 2;b.sum = 3;
    c.id = 3;c.sum = 6;
    q1.push(a);
    q1.push(b);
    q1.push(c);
    cout<<"q1:"<<endl;
    while(!q1.empty()){
        Node temp = q1.top();
        q1.pop();
        cout<<"id:"<<temp.id<<" "<<"sum:"<<temp.sum<<endl;
    }
        
    //测试样例2:
    Node2 A,B,C;
    A.id = 1;A.sum = 3;
    B.id = 2;B.sum = 20;
    C.id = 3;C.sum = 1;
    q2.push(A);
    q2.push(B);
    q2.push(C);
    cout<<"q2:"<<endl;
    while(!q2.empty()){
        Node2 temp = q2.top();
        q2.pop();
        cout<<"id:"<<temp.id<<" "<<"sum"<<temp.sum<<endl;
    }
    return 0;
}



版权声明:本文为qq_52466006原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。