《STL》queue和priority_queue(C++详细总结)

本文详细介绍了标准模板库(STL)中的队列(queue)和优先队列(priority_queue)的使用方法,包括它们的特点、成员函数及如何通过定义排序优先级来操作优先队列。此外,还提供了代码示例,展示了如何初始化、输出队列和优先队列,并解释了优先队列的内部实现机制。

特点

  1. queue:先进先出
  2. priority_queue:先进先出,不过可以定义排序优先级。

成员函数

队列:

empty()如果队列空则返回真

front()返回第一个元素

pop()删除第一个元素

push()在末尾加入一个元素

size()返回队列中元素的个数

优先队列:

back()返回最后一个元素

empty()如果队列空则返回真

top()返回第一个元素

pop()删除第一个元素

push()在末尾加入一个元素

size()返回队列中元素的个数

注意

对于优先队列的定义,有两种方式。

 priority_queue<Example> pq1;
 priority_queue<int,vector<int>,less<int>>q2;//神奇的降序
 priority_queue<Example2,vector<Example2>, cmp> pq2;

这里解释以下priority_queue<int,vector,greater>q的形式。
大家可以看到,默认模板有三个参数,第一个是优先队列处理的类。第二个参数比较有特点,是容纳优先队列的容器。实际上,优先队列是由这个容器C++语言中关于heap的相关操作实现的。这个容器默认是vector,也可以是dequeue,因为后者功能更强大,而性能相对于vector较差,考虑到包装在优先队列后,后者功能并不能很好发挥,所以一般选择vector来做这个容器。第三个参数比较重要,支持一个比较结构,默认是less,默认情况下,会选择第一个参数决定的类的<运算符来做这个比较函数。

接下来开始坑爹了,虽然用的是less结构,然而,队列的出队顺序却是greater的先出,即降序!就是说,这里这个参数其实很傲娇,表示的意思是如果!cmp,则先出列,不管这样实现的目的是啥,大家只能接受这个实现。

一般对于单维的数据,我们可以直接用greater<类>(升序),或less<类>(降序)的方式去实现优先队列的优先级定义。对于多维,有类自排序,和定义比较函数cmp的方式来进行操作。很一致的是,对于多维定义的比较函数,优先队列依然处理的方式是!cmp 即你定义的是升序,它会排成降序。

代码展示

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<math.h>
#include<set>
#include<list>
#include<string>
#include<random>
#define maxn 50

using namespace std;

struct Example{
    int x,y;
    bool operator <(const Example & a) const
    {
        if(x==a.x)
            return a.y<y;//升序排序
        return x<a.x;//降序排序
    }
};

struct Example2{
    int x,y;
};


struct cmp{
    bool operator () (const Example2 &a,const Example2 &b)const
    {
         if(b.x==a.x)
            return a.y<b.y;//降序排序
        return b.x<a.x;//升序排序
    }
};



void init( queue<int>& q)
{
    default_random_engine e;
    uniform_int_distribution<unsigned> u(0, 9);//产生随机数,0到9的闭区间。
    cout<<"初始化给queue值:";
    for(int i=0; i<10; ++i)
        {
            int value=u(e);
            cout<<value<<" ";
            q.push(value);
        }
    cout<<endl;
}

void output(queue<int> q)
{
    cout<<"输出queue:"<<endl;
    while(!q.empty())
    {
        cout<<q.front()<<" ";
        q.pop();
    }
    cout<<endl;
}

void init1(priority_queue<int,vector<int>,greater<int> >&q)
{
    default_random_engine e;
    uniform_int_distribution<unsigned> u(0, 9);//产生随机数,0到9的闭区间。
    cout<<"初始化给priority_queue值:";
    for(int i=0; i<10; ++i)
        {
            int value=u(e);
            cout<<value<<" ";
            q.push(value);
        }
    cout<<endl;
}

void output1( priority_queue<int,vector<int>,greater<int> >q)
{
    cout<<"输出priority_queue(great<int>):"<<endl;
    while(!q.empty())
    {
        cout<<q.top()<<" ";
        q.pop();
    }
    cout<<endl;
}

void init2( priority_queue<Example>& q)
{
    default_random_engine e;
    uniform_int_distribution<unsigned> u(0, 9);//产生随机数,0到9的闭区间。
    cout<<"初始化给优先队列值:";
    for(int i=0; i<10; ++i)
        {
            int valueX=u(e);
            int valueY=u(e);
            cout<<valueX<<","<<valueY<<" ";
            q.push({valueX,valueY});
        }
    cout<<endl;
}

void output2(priority_queue<Example> q)
{
    cout<<"输出priority_queue (类自带排序):"<<endl;
    while(!q.empty())
    {
        cout<<q.top().x<<","<<q.top().y<<" ";
        q.pop();
    }
    cout<<endl;
}

void init3( priority_queue<Example2,vector<Example2>, cmp> & q)
{
    default_random_engine e;
    uniform_int_distribution<unsigned> u(0, 9);//产生随机数,0到9的闭区间。
    cout<<"初始化给priority_queue值:";
    for(int i=0; i<10; ++i)
        {
            int valueX=u(e);
            int valueY=u(e);
            cout<<valueX<<","<<valueY<<" ";
            q.push({valueX,valueY});
        }
    cout<<endl;
}

void output3(priority_queue<Example2,vector<Example2>, cmp> q)
{
    cout<<"输出优先队列(自定义cmp):"<<endl;
    while(!q.empty())
    {
        cout<<q.top().x<<","<<q.top().y<<" ";
        q.pop();
    }
    cout<<endl;
}


int main()
{
    queue<int> q1;
    init(q1);
    output(q1);
    cout<<"最后一个元素:"<<q1.back()<<endl;
    cout<<"queue的大小:"<<q1.size()<<endl;

    priority_queue<int,vector<int>,greater<int>>q2;//神奇的升序。 less<int> 神奇的降序
    init1(q2);
    output1(q2);


    priority_queue<Example> pq1;
    init2(pq1);
    output2(pq1);

    priority_queue<Example2,vector<Example2>, cmp> pq2;
    init3(pq2);
    output3(pq2);

    return 0;
}

结果展示:

结果

再提一点:

随机数参考:c++ 11 random库的简单用法
参考:优先队列

### 一、queue priority_queue 的定义 `queue` 是一种 FIFO(First In First Out,先进先出)的线性数据结构[^4]。这意味着最早进入队列的元素会最先被移除。 而 `priority_queue` 则是一种基于堆的数据结构,其核心特点是:无论何时插入新元素,队列头部总是具有最高优先级的元素[^1]。默认情况下,`priority_queue` 使用最大堆来实现,因此顶部元素是当前队列中最大的值。 --- ### 二、queue priority_queue 的主要区别 #### 1. 数据存取逻辑 - **Queue**: 遵循严格的 FIFO 原则,即最先进入队列的元素会被最先取出。 - **Priority Queue**: 不遵循 FIFO 原则,而是依据元素的优先级决定哪个元素应被最先取出。通常来说,优先级最高的元素会在队首位置[^4]。 #### 2. 底层实现机制 - **Queue**: 默认使用双端队列 (`deque`) 实现,支持两端操作 (front back)[^4]。 - **Priority Queue**: 默认使用向量 (`vector`) 结合堆算法实现,底层是一个完全二叉树表示的最大堆或最小堆[^3]。 #### 3. 插入与删除效率 - 对于普通的 `queue`,插入删除的时间复杂度均为 O(1),因为只需要调整队尾或队头指针即可完成相应操作。 - 而对于 `priority_queue`,由于每次都需要维护堆性质,插入时间为 O(log n),弹出同样为 O(log n) 时间复杂度[^5]。 #### 4. 自定义比较函数的支持程度 - **Queue**: 不允许自定义排序规则,仅能按固定顺序依次进出。 - **Priority Queue**: 支持通过模板参数传递自定义比较器(如 `std::greater<T>` 或其他用户定义的谓词类),从而灵活改变优先级判断标准[^5]。 --- ### 三、queue priority_queue 的典型应用场景 #### 1. Queue 的适用场景 当需要严格按照时间序列处理任务或者消息时可以考虑使用普通队列。例如: - CPU调度中的轮转法(Round Robin Scheduling) - 广度优先搜索(BFS) ```cpp #include <iostream> #include <queue> using namespace std; void demoQueue() { queue<int> q; q.push(1); q.push(2); cout << "Front item: " << q.front() << endl; // 输出 Front item: 1 q.pop(); cout << "After pop, front item: " << q.front() << endl; // After pop, front item: 2 } ``` #### 2. Priority Queue 的适用场景 如果希望根据某些特定条件动态安排待办事项,则更适合选用带权重管理功能的优先权队列。比如: - Dijkstra算法求解单源最短路径问题; - Huffman编码构建最优前缀码表过程等等。 下面展示了一个简单的例子演示如何利用 C++ STL 提供的功能创建一个小顶堆: ```cpp #include <functional> #include <queue> #include <vector> #include <iostream> using namespace std; void demoPriorityQueue(){ vector<int> nums = {2, 9, 1, 6, 7, 4 ,0}; priority_queue<int,vector<int>,greater<int>> minHeap(nums.begin(),nums.end()); while(!minHeap.empty()){ cout<<minHeap.top()<<" "; minHeap.pop(); } } // Output will be : 0 1 2 4 6 7 9 ``` --- ### 四、总结对比表格 | 特性 | Queue | Priority Queue | |---------------------|----------------------------------|------------------------------------| | 存储模型 | FIFO | 根据优先级 | | 底层实现 | deque | vector | | 插入/删除复杂度 | O(1)/O(1) | O(log N)/O(log N) | | 是否可定制排序 | 否 | 可 | ---
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值