【总结】C++ 基础数据结构 —— STL之优先队列(priority_queue) 用法详解



一、priority_queue 的概念

  1. 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除,即具有最高级先出 (largest-in,first-out)的行为特征。

  2. 优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的



二、priority_queue 的基本操作

使用STL标准库的优先队列时,应包含头文件:#include <queue>

1、定义

	priority_queue<Type> q;

	priority_queue<Type, Container, Functional> q;

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

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

	//注意后面两个“>”不要写在一起,“>>”是右移运算符

Type为数据类型, Container为保存数据的容器,Functional为元素比较方式。
(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。使用基本数据类型时,即不写后两个参数,那么STL容器默认用的是vector,比较方式默认用operator<,也就是大顶堆,队头元素最大。)



2、基本操作

	q.empty()          如果队列为空,则返回true,否则返回false

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

	q.pop()            删除队首元素,但不返回其值

	q.top()            返回具有最高优先级的元素值,但不删除该元素

	q.push(item)       在基于优先级的末尾插入新元素

注意: 优先队列没有 q.back() 操作



三、priority_queue 的用法


1、基本用法

#include<iostream>
#include <queue>
using namespace std;
int main(){
    //对于基础类型 默认是大顶堆,降序队列 
    priority_queue<int> q1; 
    //等同于 priority_queue<int, vector<int>, less<int> > a;
    
    //             这里一定要有空格,不然成了右移运算符↓
    priority_queue<int, vector<int>, greater<int> > q2;  //小顶堆,升序队列 
    priority_queue<string> q3;
    for(int i=0; i<5; i++){
        q1.push(i);
        q2.push(i);
    }
    while(!q1.empty()){		//输出大顶堆 
        cout<<q1.top()<<' ';
        q1.pop();
    } 
    cout<<endl;
    while(!q2.empty()){		//输出小顶堆 
        cout<<q2.top()<<' ';
        q2.pop();
    }
    cout<<endl;
    q3.push("abc");
    q3.push("abcd");
    q3.push("cbd");
    while (!q3.empty()){	//输出字符串大顶堆 
        cout<<q3.top()<<' ';
        q3.pop();
    } 
    cout<<endl;
    return 0;
}

输出结果:
在这里插入图片描述


2、pari<Type, Type>类型

先比较第一个元素,如果第一个相等则比较第二个

#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main(){
    priority_queue<pair<int, int> > q1;
    priority_queue<pair<string, string>, vector<pair<string, string> >, greater<pair<string, string> > > q2;
    
    pair<int, int> a1(1, 2);
    pair<int, int> a2(1, 3);
    pair<int, int> a3(2, 5);
    
    q1.push(a1);
    q1.push(a2);
    q1.push(a3);
    
    pair<string, string> b1("zf", "akl");
    pair<string, string> b2("acd", "azkl");
    pair<string, string> b3("acd", "ab");
    
    q2.push(b1);
    q2.push(b2);
    q2.push(b3);
    
    while(!q1.empty()){
        cout<<q1.top().first<<' '<<q1.top().second<< '\n';
        q1.pop();
    }
    while(!q2.empty()){
        cout<<q2.top().first<<' '<<q2.top().second<< '\n';
        q2.pop();
    }
}

输出结果:
在这里插入图片描述

3、自定义类型

方法1: 重载 operator< ,返回true时,说明左边形参的优先级低于右边形参

#include <iostream>
#include <queue> 
#include <cstdlib>
using namespace std;
struct Node{
    int x, y;
    Node(int a=0, int b=0):
        x(a),y(b){}
};
bool operator<(Node a, Node b){		//返回true时,说明a的优先级低于b

    if( a.x== b.x ) 		//x相等时,y大的优先级低(y小的Node排在队前)
		return a.y> b.y;	
    return a.x> b.x; 		//x值较大的Node优先级低(x小的Node排在队前)
}
int main(){
    priority_queue<Node> q;
    for(int i=0; i<10; ++i)
   		q.push( Node( rand(), rand() ) );
    while(!q.empty()){
        cout<<q.top().x<<' '<<q.top().y<<endl;
        q.pop();
    }
    return 0;
}

输出结果:
在这里插入图片描述
注意: 自定义类型重载operator<后,声明对象时就可以只带一个模板参数。但此时不能像基本类型那样声明 priority_queue<Node, vector<Node>, greater<Node> >,因为greater<Node>没有定义。

如果想用这种方法定义 priority_queue<Node, vector<Node>, greater<Node> > 则要重载 operator > ,将方法2。

方法2: 重载 operator> ,返回的是小顶堆。但一般很少这样用,更多的是重载operator< 。

#include <iostream>
#include <queue>
#include <cstdlib>
using namespace std;
struct Node{
    int x, y;
    Node(int a=0, int b=0):
        x(a), y(b) {}
};
bool operator> ( Node a, Node b ){		//返回true,a的优先级大于b
    
    if(a.x== b.x) 		//x相同时,y大的排在队前部
		return a.y> b.y;
    return a.x> b.x; 		//x大的排在队前部;
}
int main(){
    priority_queue<Node,vector<Node>,greater<Node> > q;
    for(int i=0; i<10; ++i)
    q.push( Node( rand(), rand() ) );
    while(!q.empty()){
        cout<<q.top().x<<' '<<q.top().y<<endl;
        q.pop();
    }
    return 0;
}

输出结果:
在这里插入图片描述

方法3: 重写仿函数,返回值排序与方法1、方法2相同,都是小顶堆。

#include <iostream>
#include <queue>
#include <cstdlib>
using namespace std;
struct Node{
    int x, y;
    Node(int a=0, int b=0):
        x(a), y(b) {}
};
struct cmp{			//重写的仿函数

	//返回true时,a的优先级低于b的优先级(a排在b的后面)
    bool operator() ( Node a, Node b ){			//默认是less函数
        
        if(a.x==b.x) 
			return a.y> b.y;      
        return a.x> b.x; 
	}
};
int main(){                        //仿函数替换默认比较方式
    priority_queue<Node, vector<Node>, cmp> q;
    for(int i=0; i<10; ++i)
    	q.push( Node( rand(), rand() ) );
    while(!q.empty()){
        cout<<q.top().x<<' '<<q.top().y<<endl;
        q.pop();
    }
    return 0;
}

输出结果:
在这里插入图片描述

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值