C++STL之优先队列

首先先讲一下仿函数

仿函数

仿函数(functor),就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。仿函数的主要功能是为了搭配STL算法使用,单独使用仿函数的情况比较少。 (感谢百度百科)

可能你看了以后也还是不太明白它到底是干什么的,怎么作用的,那么我就来简单讲一下

仿函数就是带有一个或多个重载小括号的成员函数的一个结构体或类,又叫做仿函数类

仿函数类既可以当函数用,又可以当结构体用,好处是这样就可以通过传递模板类来给STL传递一个你写的函数

如下

#include <bits/stdc++.h>
using namespace std;
struct disp{
	void operator()(int x){
		cout<<x<<endl;
	}
};
int main(){
	disp()(2);
	return 0;
}

实现了一个输出 int x 的函数功能

对于传递模板类就要说到今天的正题了--优先队列--priority_queue

优先队列,本质不是队列,而是堆,且默认大根(顶)堆

声明定义:priority_queue <T,Container,Compare>

T是数据类型

Container是underlying container,底层容器,用来作为优先队列的内部实现

Compare是数据排列方式的比较,需要传入仿函数类

需要注意的点有如下几条:

①当T类型拥有小于号的比较功能时,Container和Compare可省略,默认为vector和less

②Container不是随意一个都可以,必须是有迭代器减法功能的容器才行

    (看了优先队列内部代码后,发现功能的实现过程中有迭代器减法)

    这类容器一般都是内存地址连续(迭代器连续),一般可由下标访问

    博主已知的有 deque,vector,array

    其中array内存大小需要设置,并非无限,所以不常用

    对于deque和vector用于priority_queue的区别

    博主可以负责任的告诉你:没有区别!priority_queue内部的实现不涉及二者差异的部分

    并且priority_queue带给用户的接口也很狭窄,不涉及deque和vector的功能

③T类型如果是你自定义的结构体或类,例如node

    那么下面说的是必须的

    你要么node里重载小于号,要么写一个仿函数类

    less<node>这种东西可没有

优先队列的声明与定义:

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
struct node{
	int x;
	bool operator<(node a)const{
		return x<a.x;
	}
};
struct node2{
	int x;
	friend bool operator<(node2 a,node2 b){
		return a.x<b.x;
	}
};
struct cmp{
	bool operator()(int a,int b){
		return a<b;
	}
};
int main(){
	priority_queue<int> q0;
	priority_queue<int,vector<int>,less<int>> q1;
	priority_queue<int,deque<int>,less<int>> q2;
	priority_queue<int,array<int,100>,less<int>> q3;
	priority_queue<int,vector<int>,cmp> q4;
	priority_queue<node> q5;
	priority_queue<node2> q6;
	return 0;
}

以上所有写法全是大根堆(top大),小根同理

然后注意!node里那个成员函数必须写const!!!

常成员函数与非常成员函数是不同的函数,内部实现用的是常成员函数!

友元函数的话就不需要担心这个了,常还是非常只有成员函数有

再就是 如果写 const node &的话会快很多,遇到卡时间的题会很有效,但是写或不写都不会涉及编译bug

常成员函数的那个const一定不能缺!不能缺!

然后总有人会问,为啥less大根,来看下less和greater的内部代码

/// One of the @link comparison_functors comparison functors@endlink.
  template<typename _Tp>
    struct less : public binary_function<_Tp, _Tp, bool>
    {
      bool
      operator()(const _Tp& __x, const _Tp& __y) const
      { return __x < __y; }
    };

/// One of the @link comparison_functors comparison functors@endlink.
  template<typename _Tp>
    struct greater : public binary_function<_Tp, _Tp, bool>
    {
      bool
      operator()(const _Tp& __x, const _Tp& __y) const
      { return __x > __y; }
    };

怎么说呢,举个例子吧

比方说 a[5]={3,1,5,4,2};

sort(a,a+5,less<int>());

结果就是:1,2,3,4,5

对于队列,queue也好,deque也好

下标小的是front(迭代器begin),下标大的是back(迭代器end)

对于priority_queue,top不是front,而是back,所以这东西和队列没啥关系,鬼知道名字怎么起的

类似于stack,是在后端操作的

priority_queue按less从小到大排的话,后端就是大的,于是就是大根堆

讲了这么多大家大概已经彻底理解这个这个priority_queue是啥,大概如何实现的吧

最后就该讲最简单的部分了

一些操作(成员函数):

priority_queue<int> q;
q.push(x);//压入堆顶
q.emplace(x);//压入堆顶
q.empty();//是否空
q.size();//个数
q.swap(q2);//交换
q.top();//堆顶元素的引用

好,大概就这些,我觉得算是挺详细的了,应该能对大家学习有很大帮助

发布了49 篇原创文章 · 获赞 0 · 访问量 1721

猜你喜欢

转载自blog.csdn.net/weixin_44077863/article/details/102020177