优先队列——大小堆—— priority_queue

2024-05-12 00:36

本文主要是介绍优先队列——大小堆—— priority_queue,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本人博客主页

本篇博客相关博客

二叉树--讲解

文章目录

  • 目录

    文章目录

    前言

    一、priority_queue是什么?

    二、priority_queue的使用

    1、相关函数

    2、代码使用

    3、堆的插入删除

    三、模拟实现

    1、大框架

    2、仿函数

    3、向下调整 

    4、向下调整

    总结



前言

在我们学习二叉树时接触过大小堆;

大堆:在一颗完全二叉树中,大数在堆顶,小数在下方;

小堆:乃相反,在完全二叉树中,最小的数在堆顶,大数在下方;


提示:以下是本篇文章正文内容,下面案例可供参考

一、priority_queue是什么?

1. 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。

2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元 素)。

3. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特 定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先队列的顶部。

4. 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭 代器访问,并支持以下操作:

empty():检测容器是否为空

size():返回容器中有效元素个数

front():返回容器中第一个元素的引用

push_back():在容器尾部插入元素

pop_back():删除容器尾部元素

二、priority_queue的使用

优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成 堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。注意: 默认情况下priority_queue是大堆。

1、相关函数

2、代码使用

代码如下(示例):

void test_priority_queue()
{//priority_queue<int, vector<int>, greater<int>> pq;priority_queue<int> pq;//定义一个堆;默认为大堆//priority_queue<int, deque<int>> pq;
//向堆里压入数据pq.push(1);pq.push(0);pq.push(5);pq.push(2);pq.push(1);pq.push(7);
//通过push函数将数据大的数据就放到堆顶了while (!pq.empty())//堆不是空就进行循环{cout << pq.top() << " ";//打印堆顶数据pq.pop();//弹出堆顶数据}cout << endl;
}

 我们默认建立的是大堆,所以在压入数据时,在vector末尾压入数据,然后通过向上调整,比较大的数就到堆顶了。

弹出数据时,我们将堆顶的数据和末尾的数据进行交换,然后将末尾数据删除,再将堆顶的数据向下调整。

在模拟实践时会细讲。

3、堆的插入删除

先插入一个10到数组的尾上,再进行向上调整算法,直到满足堆。

删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调 整算法。 

三、模拟实现

1、大框架

代码如下(示例):

template<class T, class Container = vector<T>, class Comapre = less<T>>
class priority_queue
{
public:	void push(const T& x){_con.push_back(x);adjust_up(_con.size() - 1);}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjust_down(0);}const T& top(){return _con[0];}size_t size(){return _con.size();}bool empty(){return _con.empty();}
private:Container _con;
};

2、仿函数

我们在向上调整和向下调整时,我们可以用同一份代码,只有父亲节点和孩子节点的大小关系的区别,这时我们就用了仿函数,当我们想要建大堆时,我们不需要向上下调整函数传递任何参数,这时候我们默认就用的less函数里的对括号的重载,即x<y的大小关系。

当我们想要建小堆时,我们传一个函数参数,然comapre这个类具有greater这个类型的性质,这时候com对象遇到括号和括号结合就调用x>y这个函数了 。

仿函数和c语言中的函数调用非常像,区别在于传递的参数,c语言传递的是函数参数,这里我们传递的是模板参数。

代码

template<class T>
struct less
{bool operator()(const T& x, const T& y){return x < y;}
};template<class T>
struct greater
{bool operator()(const T& x, const T& y){return x > y;}
};

3、向下调整 

我们建立大堆和小堆时,孩子节点和父亲节点的大小关系有所差异。所以我们这里借助了仿函数。

void adjust_down(int parent)
{size_t child = parent * 2 + 1;while (child < _con.size()){Comapre com;//if (child + 1 < _con.size() //	&& _con[child] < _con[child + 1])if (child + 1 < _con.size()&& com(_con[child], _con[child + 1]))//我们这里调用了com这个对象了的对括号的重载{++child;}//if (_con[parent] < _con[child])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

4、向下调整

	void adjust_up(int child){Comapre com;int parent = (child - 1) / 2;while (child > 0){//if (_con[parent] < _con[child])if (com(_con[parent], _con[child]))//if (Comapre()(_con[parent], _con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}

 


总结

会用priority_queue的各个函数和理解堆

掌握仿函数的调用和函数的重载

这篇关于优先队列——大小堆—— priority_queue的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/981107

相关文章

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 2431 poj 3253 优先队列的运用

poj 2431: 题意: 一条路起点为0, 终点为l。 卡车初始时在0点,并且有p升油,假设油箱无限大。 给n个加油站,每个加油站距离终点 l 距离为 x[i],可以加的油量为fuel[i]。 问最少加几次油可以到达终点,若不能到达,输出-1。 解析: 《挑战程序设计竞赛》: “在卡车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站i时,就获得了一

C++——stack、queue的实现及deque的介绍

目录 1.stack与queue的实现 1.1stack的实现  1.2 queue的实现 2.重温vector、list、stack、queue的介绍 2.1 STL标准库中stack和queue的底层结构  3.deque的简单介绍 3.1为什么选择deque作为stack和queue的底层默认容器  3.2 STL中对stack与queue的模拟实现 ①stack模拟实现

poj3750约瑟夫环,循环队列

Description 有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。 Input 第一行输入小孩的人数N(N<=64) 接下来每行输入一个小孩的名字(人名不超过15个字符) 最后一行输入W,S (W < N),用

POJ2010 贪心优先队列

c头牛,需要选n头(奇数);学校总共有f的资金, 每头牛分数score和学费cost,问合法招生方案中,中间分数(即排名第(n+1)/2)最高的是多少。 n头牛按照先score后cost从小到大排序; 枚举中间score的牛,  预处理左边与右边的最小花费和。 预处理直接优先队列贪心 public class Main {public static voi

Java并发编程之——BlockingQueue(队列)

一、什么是BlockingQueue BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种: 1. 当队列满了的时候进行入队列操作2. 当队列空了的时候进行出队列操作123 因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空

ActiveMQ—Queue与Topic区别

Queue与Topic区别 转自:http://blog.csdn.net/qq_21033663/article/details/52458305 队列(Queue)和主题(Topic)是JMS支持的两种消息传递模型:         1、点对点(point-to-point,简称PTP)Queue消息传递模型:         通过该消息传递模型,一个应用程序(即消息生产者)可以

深度优先(DFS)和广度优先(BFS)——算法

深度优先 深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支,当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访