STL之priority_queue的用法

priority_queue的用法:这里先将一下STL里面的heap(堆),再来将如何使用heap来实现优先队列

在STL里面:

下面介绍STL中与堆相关的4个函数——建立堆make_heap(),在堆中添加数据push_heap(),在堆中删除数据pop_heap()和堆排序sort_heap():

头文件 #include <algorithm>

下面的_First与_Last为可以随机访问的迭代器(指针),_Comp为比较函数(仿函数),其规则——如果函数的第一个参数小于第二个参数应返回true,否则返回false。

建立堆

make_heap(_First, _Last, _Comp)

默认是建立最大堆的。对int类型,可以在第三个参数传入greater<int>()得到最小堆。

在堆中添加数据

push_heap (_First, _Last)

要先在容器中加入数据,再调用push_heap ()

在堆中删除数据

pop_heap(_First, _Last)

要先调用pop_heap()再在容器中删除数据

 

堆排序

sort_heap(_First, _Last)

排序之后就不再是一个合法的heap了

优先队列priority_queue是调用 STL里面的 make_heap(), pop_heap(), push_heap() 算法实现,也算是堆的另外一种形式。
这里我们先写一个用 STL 里面堆算法实现的与真正的STL里面的 priority_queue用法相似的priority_queue, 以加深对优先队列的理解:代码如下:

#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;

class my_priority_queue
{
private:
	vector<int> data;

public:
	void push(int t)
	{
		//加入新数据 先在容器中加入,再调用push_heap()
		data.push_back(t);
		push_heap(data.begin(), data.end());
	}

	void pop()
	{
		//删除数据  要先调用pop_heap(),再在容器中删除
		pop_heap(data.begin(), data.end());
		data.pop_back();
	}

	int top() { return data.front(); }
	int size() { return data.size(); }
	bool empty() { return data.empty(); }
};

int main()
{
	my_priority_queue test;
	test.push(3);
	test.push(5);
	test.push(2);
	test.push(4);

	while (!test.empty()){
		cout << test.top() << endl;
		test.pop();
	}

	return 0;
}

STL里面的 priority_queue 写法与此相似,只是增加了模板及相关的迭代器什么的。

priority_queue 对于基本类型的使用方法相对简单。他的模板声明带有三个参数:

priority_queue<Type, Container, Functional>

其中Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。

Container 必须是用数组实现的容器,比如 vector, deque 但不能用 list.

STL里面默认用的是 vector. 比较方式默认用 operator< , 所以如果你把后面俩个参数缺省的话,

优先队列就是大顶堆,队头元素最大。

#include <iostream>
#include <queue>

using namespace std;

int main(){
	priority_queue<int> q;

	for (int i = 0; i< 10; ++i) q.push(rand());
	while (!q.empty()){
		cout << q.top() << endl;
		q.pop();
	}

	getchar();
	return 0;
}

如果要用到小顶堆,则一般要把模板的三个参数都带进去。

STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆

#include <iostream>
#include <queue>
#include<algorithm>
#include <functional>
using namespace std;

int main(){

	priority_queue<int, vector<int>, greater<int>> q;

	for (int i = 0; i< 10; ++i) q.push(rand());
	while (!q.empty()){
		cout << q.top() << endl;
		q.pop();
	}

	getchar();
	return 0;
}

对于自定义类型,则必须自己重载 operator< 或者自己写仿函数:如下面自定义的结构体类型,必须重载比较函数,如何不重载,则不能通过编译:

#include <iostream>
#include <queue>

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)
{
	return a.x< b.x;
}

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> 没有定义,如果想用这种方法定义则可以按如下方式:

//下面代码实现的是一个小顶堆
#include <iostream>
#include <queue>

using namespace std;

struct Node{
	int x, y;
	Node(int a = 0, int b = 0) :
		x(a), y(b) {}
};

struct cmp
{
	bool operator() (Node a, Node b)
	{
		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;
}

ps:如果重载operator
> 可直接使用priority_queue<Node,vector<Node>,greater<Node>>

时间: 2024-08-03 18:36:29

STL之priority_queue的用法的相关文章

STL之priority_queue(优先队列)

priority_queue是一个容器适配器,在这个容器里第一个数据元素是最大的.它的使用场景是什么样:如果12306抢票,为什么黄牛能抢这么多票,感觉12306那边的请求队列是一个优先队列,黄牛的请求携带了一个隐含参数,所以他的请求最先执行.当然这是怀疑.不过也是优先级队列的使用场景.还可以进行排序,把数据压入优先队列中,然后出队列就是由大到小排列了 注意:stl的priority_queue容器需要一个boolean operator<(const T& ,const T&)函数

STL 之 map的用法

Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道.这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处. 下面举例说明什么是一对一的数据映射.比如一个班级中,每个学生的学号跟他的姓名就存在着一一

(转)STL中set的用法

转载自here 1.关于set map容器是键-值对的集合,好比以人名为键的地址和电话号码.相反地,set容器只是单纯的键的集合.例如,某公司可能定义了一个名为bad_checks的set容器,用于记录曾经给本公司发空头支票的客户.当想知道一个值是否存在时,使用set容器是最适合的.除了两种例外情况,set容器支持大部分的map操作,这两种例外是:set不支持下标操作,而且也没有mapped_type类型,在set容器中,value_type不是pair类型,而是与key_type相同的类型.它

STL中mem_fun, mem_fun_ref用法

1.引言 先看一个STL中for_each的用法: 1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <functional> 5 #include <iterator> 6 using namespace std; 7 class Test 8 { 9 public: 10 Test(int _data = 0):data(_data){} 1

STL学习——Priority_queue篇

STL学习--Priority_queue篇 概述 priority_queue是一个拥有权值观念的queue,它允许加入新元素,移除旧元素,审视元素值等功能.因为它是queue,故只允许底端加入元素,顶端取出元素.priorit_queue内元素并非依照被推入的次序排列,而是依照元素权值排列.权值最高者,排在最前面. 实现 priority_queue利用max_heap和vector表现的完全二叉树实现.它的实现完全以底部容器为根据,并使用heap处理规则,故实现简单.默认情况,使用vect

STL list链表的用法详解(转)

本文以List容器为例子,介绍了STL的基本内容,从容器到迭代器,再到普通函数,而且例子丰富,通俗易懂.不失为STL的入门文章,新手不容错过! 0 前言 1 定义一个list 2 使用list的成员函数push_back和push_front插入一个元素到list中 3 list的成员函数empty() 4 用for循环来处理list中的元素 5 用STL的通用算法for_each来处理list中的元素 6 用STL的通用算法count_if()来统计list中的元素个数 7 使用count_i

(转)C++ STL中list的用法

博客搬家啦http://t.cn/RvFZs2c STL中list的用法 C++ Lists(链表) 赋值(assign) 语法: void assign( input_iterator start, input_iterator end ); void assign( size_type num, const TYPE &val ); assign()函数以迭代器start和end指示的范围为list赋值或者为list赋值num个以val为值的元素. 相关主题: insert(), back

STL中map的用法

map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道.这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处. 下面举例说明什么是一对一的数据映射.比如一个班级中,每个学生的学号跟他的姓名就存在着一一

C++ STL之priority_queue

STL中的priority_queue(优先队列)是一种会按照自定义的一种方式(数据的优先级)来对队列中的数据进行动态的排序的容器,不同优先级的情况下,top()上永远是最高优先级的数据,其底层采用的是堆结构(默认大顶堆).注意相同优先级下并没有先进先出,后面的例子中可以看到 头文件#include<queue> 标准库默认使用元素类型的<操作符来确定它们之间的优先级关系,数据越大优先级越高,想要改变优先级的界定方式的话需要重载<操作符. 先看个最简单的: #include<