快速入手优先队列

一.理解优先队列

标准模板库(Standard Template Library,STL)

C++功能强大,为开发者提供了标准模板库,其中封装了很多实用的容器。容器可以理解成能够实现很多功能的系统函数,或者说用来存放数据的对象,开发者可以根据接口规范(调用格式)直接调用,而不用关心其内部实现的原理和具体代码,十分方便快捷。

常见的容器有vector、stack、queue、map、set等。

优先队列(priority_queue)

STL 的容器中还有两种容器与队列有关,分别是双端队列(deque)和优先队列(priority_queue)。

priority_queue翻译为优先队列,一般用来解决一些贪心问题,其底层是用“堆”来实现的。

在优先队列中,任何时刻,队首元素一定是当前队列中优先级最高(优先值最大)的那一个(大根堆),也可以是最小的那一个(小根堆)。

可以不断往优先队列中添加某个优先级的元素,也可以不断弹出优先级最高的那个元素,每次操作其会自动调整结构,始终保证队首元素的优先级最高。

二.优先队列定义

定义和使用priority_queue前,也只要添加queue头文件(#include<queue>)。定义一个priority_queue的方法为:

priority_queue<typename> name;

其中,typename可以是任何基本类型或者容器,name为优先队列的名字。通过top()或pop()访问队首元素(也称堆顶元素),也就是优先级最高的元素。对于可以直接使用的基本数据类型(int等),优先队列对它们的优先级设置一般是数字越大的优先级越高(对于char,则是字典序最大的)。

三.prtority_queue的常用函数

(1)push()

push(x)是将x加入优先队列,时间复杂度为O(logn),n为当前优先队列中的元素个数。加入后会自动调整priority_queue的内部结构,以保证队首元素(堆顶元素)的优先级最高。

(2)top()

top)是获得队首元素(堆顶元素),时间复杂度为O(1)。

扫描二维码关注公众号,回复: 14715392 查看本文章

(3)pop()

popO是让队首元素(堆顶元素)出队,时间复杂度为O(logn),n为当前优先队列中的元素个数。出队后会自动调整priority_queue的内部结构,以保证队首元素(堆顶元素)的优先级最高。

四.定义排列方式

默认优先队列中的元素按照从大到小的顺序排列;若想从小到大排列有三种方法

  1. 输出元素乘以-1

  1. 利用C++funtional函数

  1. 与sort()函数类似,自己定义函数指针/函数对象/函数类模版对象

priority_queue <int> q1; //定义heap为一个int类型的优先队

priority_queue <double> q2; //定义k为一个double类型的优先队列

这两种定义方式都是大根堆,想要使其变成小根堆,可以将每个数据都乘以-1,输出再乘回-1

priority_queue<int,vector<int>,greater<int> >que3;//注意“>>”会被认为错误,所以中间要加上空格

priority_queue<int,vector<int>,less<int> >que4;最大值优先

五.greater<int>与less<int>

很多人greater和less会混淆,其实虽然greater有更大的意思,但构建的是小顶堆,可我们换个角度想,这个小顶堆弹出去的都是小的,留下来的就是更大的了!

这有个例题方便理解

题目

问题描述:给定n个正整数,删除最大的n1个数和最小的n2个数,并计算其余正整数的平均值。
·输入:输入由多组测试用例组成。每组测试用例由两行组成。
第一行包含三个整数n1,n2和n(1<=n1,n2<=10,n1+n2<n<=5000000)由一个空格隔开。第二行包含n个正整数(对于所有的ai,1<=i<=n,1<=ai<=10^8)由一个空格隔开。最后输出测试用例为三个0。
输出:对于每组测试用例,输出删除相关元素后的平均值,并将其四舍五入到小数点后6位。

分析

·本题的数据规模很大,如果通过排序获取相关区间的元素,计算累加和,肯定会因为时间效率太低而超时。
可以采用这样的方法:引入一个大根堆和一个小根堆,输入给定的数,使大根堆保存最大的n1个数,小根堆保存最小的n2个数,再算出所有的数的总和sum。随后,将sum减去大根堆里的元素和小根堆里的元素,再计算平均数。

代码

int main(){
    int n1, n2, n, x;
    while (scanf("%d %d %d", &n1, &n2, &n) && n > 0){
        priority_queue<int, vector<int>, greater<int> >qsmall;//小根堆,保存最大的n1个数
        priority_queue<int, vector<int>, less<int> >qbig;//大根堆,保存最小的n2个数
        double sum = 0.0;
        for (int i = 0; i < n; i++){ //遍历所有的元素
            scanf("%d", &x);
            sum += x;
            qsmall.push(x);
            qbig.push(x);
            if (qsmall.size() > n2)qsmall.pop();//保存最大的n1个数
            if (qbig.size()>n2)qbig.pop();//保存最小的n2个数
        }
    }
//n1+n2<n,后面直接让总数sum减去qsmall中保存的最大的n1个数和qbig中保存的最大的n2个数即可
}

~感谢观看❥(^_-)

猜你喜欢

转载自blog.csdn.net/phantomthief1412/article/details/129685001