> 文章列表 > c++11 标准模板(STL)(std::priority_queue)(二)

c++11 标准模板(STL)(std::priority_queue)(二)

c++11 标准模板(STL)(std::priority_queue)(二)

适配一个容器以提供优先级队列
std::priority_queue

定义于头文件 <queue>

template<

    class T,
    class Container = std::vector<T>,
    class Compare = std::less<typename Container::value_type>

> class priority_queue;

priority_queue 是容器适配器,它提供常数时间的(默认)最大元素查找,对数代价的插入与释出。

可用用户提供的 Compare 更改顺序,例如,用 std::greater<T> 将导致最小元素作为 top() 出现。

用 priority_queue 工作类似管理某些随机访问容器中的堆,优势是不可能突然把堆非法化。

模板形参

T - 存储的元素类型。若 TContainer::value_type 不是同一类型则行为未定义。 (C++17 起)
Container - 用于存储元素的底层容器类型。容器必须满足序列容器 (SequenceContainer) 的要求,而其迭代器必须满足遗留随机访问迭代器 (LegacyRandomAccessIterator) 的要求。另外,它必须提供拥有通常语义的下列函数:

  • front()
  • push_back()
  • pop_back()

标准容器 std::vector 和 std::deque 满足这些要求。

Compare - 提供严格弱序的比较 (Compare) 类型。

注意 比较 (Compare) 形参的定义,使得若其第一参数在弱序中先于其第二参数则返回 true 。但因为 priority_queue 首先输出最大元素,故“先来”的元素实际上最后输出。即队列头含有按照 比较 (Compare) 所施加弱序的“最后”元素。

成员函数

构造 priority_queue

std::priority_queue<T,Container,Compare>::priority_queue

priority_queue() : priority_queue(Compare(), Container()) { }

(1) (C++11 起)

explicit priority_queue(const Compare& compare)
    : priority_queue(compare, Container()) { }

(2) (C++11 起)

explicit priority_queue( const Compare& compare = Compare(),
                         const Container& cont = Container() );

(3) (C++11 前)

priority_queue( const Compare& compare, const Container& cont );

(C++11 起)

priority_queue( const Compare& compare, Container&& cont );

(4) (C++11 起)

priority_queue( const priority_queue& other );

(5)

priority_queue( priority_queue&& other );

(6) (C++11 起)

template< class Alloc >
explicit priority_queue( const Alloc& alloc );

(7) (C++11 起)

template< class Alloc >
priority_queue( const Compare& compare, const Alloc& alloc );

(8) (C++11 起)
template< class Alloc >

priority_queue( const Compare& compare, const Container& cont,

                const Alloc& alloc );

(9) (C++11 起)
template< class Alloc >

priority_queue( const Compare& compare, Container&& cont,

                const Alloc& alloc );

(10) (C++11 起)

template< class Alloc >
priority_queue( const priority_queue& other, const Alloc& alloc );

(11) (C++11 起)

template< class Alloc >
priority_queue( priority_queue&& other, const Alloc& alloc );

(12) (C++11 起)
template< class InputIt >

priority_queue( InputIt first, InputIt last,

                const Compare& compare, const Container& cont );

(13) (C++11 起)
template< class InputIt >

priority_queue( InputIt first, InputIt last,
                const Compare& compare = Compare(),

                Container&& cont = Container() );

(14) (C++11 起)

 

从多种数据源构造容器适配器的底层容器。

1) 默认构造函数。值初始化底层容器。

2) 用 compare 的内容复制构造比较函数对象 comp 。值初始化底层容器 c

3) 用 cont 的内容复制构造底层容器 c 。用 compare 的内容复制构造比较函数对象 comp 。调用 std::make_heap(c.begin(), c.end(), comp) 。此亦为默认构造函数。 (C++11 前)

4) 用 std::move(cont) 移动构造底层容器 c 。以 compare 的内容复制构造比较函数对象 comp 。调用 std::make_heap(c.begin(), c.end(), comp) 。

5) 复制构造函数。以 other.c 的内容复制构造底层容器。以 other.comp 复制构造比较函数对象。 (隐式声明)

6) 移动构造函数。以 std::move(other.c) 构造底层容器。以 std::move(other.comp) 构造比较函数对象。 (隐式声明)

7-12) 仅若 std::uses_allocator<container_type, Alloc>::value == true ,即若底层容器是具分配器容器(对所有标准库容器为真),才定义下列构造函数。

7) 以 alloc 为分配器构造底层容器。等效地调用 c(alloc) 。值初始化 comp

8) 以 alloc 为分配器构造底层容器。等效地调用 c(alloc) 。从 compare 复制构造 comp

9) 用 cont 的内容,以 alloc 为分配器构造底层容器,如同用 c(cont, alloc) 。从 compare 复制构造 comp 。然后调用 std::make_heap(c.begin(), c.end(), comp) 。

10) 用 cont 的内容,以 alloc 为分配器并以移动语义构造底层容器,如同用 c(std::move(cont), alloc) 。从 compare 复制构造 comp 。然后调用 std::make_heap(c.begin(), c.end(), comp) 。

11) 用 other.c 的内容,以 alloc 为分配器构造底层容器。等效地调用 c(other.c, alloc) 。从 other.comp 复制构造 comp

12) 用 other 的内容,同时以 alloc 为分配器构造适配器。等效地调用 c(std::move(other.c), alloc) 。从 other.comp 移动构造 comp

13) 从 cont 复制构造 c 并从 compare 复制构造 comp 。然后调用 c.insert(c.end(), first, last); ,再调用 std::make_heap(c.begin(), c.end(), comp); 。

14) 从 std::move(cont) 移动构造 c 并从 std::move(compare) 移动构造 comp 。然后调用 c.insert(c.end(), first, last); ,再调用 std::make_heap(c.begin(), c.end(), comp); 。

参数

alloc - 用于底层容器所有内存分配的分配器
other - 用作源初始化底层容器的另一容器适配器
cont - 用作源初始化底层容器的容器
compare - 用于初始化底层比较函数对象的比较函数对象
first, last - 要初始化的元素范围
类型要求
- Alloc 必须满足分配器 (Allocator) 的要求。
- Container 必须满足容器 (Container) 的要求。仅若 Container 满足具分配器容器 (AllocatorAwareContainer) 的要求才定义构造函数 (5-10)
- InputIt 必须满足遗留输入迭代器 (LegacyInputIterator) 的要求。

复杂度

1-2) 常数。

3,5) O(N) 次比较,其中 N 为 cont.size() 。

另外,调用 O(N) 次 value_type 的构造函数,其中 N 为 cont.size() 。

4) O(N) 次比较,其中 N 为 cont.size() 。

6-8) 常数。

9) O(N) 次比较,其中 N 为 cont.size() 。

另外,调用 O(N) 次 value_type 的构造函数,其中 N 为 cont.size() 。

10) O(N) 次比较,其中 N 为 cont.size() 。

11) 与 other 的大小成线性。

12) 常数。

13) O(N) 次比较,其中 N 为 cont.size() + std::distance(first, last) 。

另外,调用 O(N) 次 value_type 的构造函数,其中 N 为 cont.size() 。

14) O(N) 次比较,其中 N 为 cont.size() + std::distance(first, last) 。

析构 priority_queue

std::priority_queue<T,Container,Compare>::~priority_queue

~priority_queue();

销毁容器适配器。调用元素的析构函数,然后解分配所用的存储。注意,若元素是指针,则不销毁所指向的对象。

复杂度

与容器适配器大小成线性。

调用示例

#include <iostream>
#include <forward_list>
#include <string>
#include <iterator>
#include <algorithm>
#include <functional>
#include <queue>
#include <deque>
#include <time.h>using namespace std;struct Cell
{int x;int y;Cell() = default;Cell(int a, int b): x(a), y(b) {}Cell &operator +=(const Cell &cell){x += cell.x;y += cell.y;return *this;}Cell &operator +(const Cell &cell){x += cell.x;y += cell.y;return *this;}Cell &operator *(const Cell &cell){x *= cell.x;y *= cell.y;return *this;}Cell &operator ++(){x += 1;y += 1;return *this;}bool operator <(const Cell &cell) const{if (x == cell.x){return y < cell.y;}else{return x < cell.x;}}bool operator >(const Cell &cell) const{if (x == cell.x){return y > cell.y;}else{return x > cell.x;}}bool operator ==(const Cell &cell) const{return x == cell.x && y == cell.y;}
};std::ostream &operator<<(std::ostream &os, const Cell &cell)
{os << "{" << cell.x << "," << cell.y << "}";return os;
}template<typename _Tp, typename _Sequence = vector<_Tp>,typename _Compare  = less<typename _Sequence::value_type> >
void queuePrint(const std::string &name,const std::priority_queue<_Tp, vector<_Tp>, _Compare> &queue)
{std::cout << name ;std::priority_queue<_Tp, vector<_Tp>, _Compare> queuep = queue;while (queuep.size() > 0){std::cout << queuep.top() << " ";queuep.pop();}std::cout << std::endl;
}struct Compare
{Compare() {}bool operator()(const Cell &a, const Cell &b)const{if (a.x == b.x){return a.y < b.y;}return a.x < b.x;}
};int main()
{std::cout << std::boolalpha;std::mt19937 g{std::random_device{}()};srand((unsigned)time(NULL));auto generate = [](){int n = std::rand() % 10 + 110;Cell cell{n, n};return cell;};//1) 默认构造函数。值初始化底层容器。std::priority_queue<Cell> queue1;std::cout << "queue1 empty: " << queue1.empty() << std::endl;std::priority_queue<Cell, std::vector<Cell>, Compare> queue3;std::cout << "queue3 empty: " << queue3.empty() << std::endl;std::cout << std::endl;std::vector<Cell> vector1(6);std::generate(vector1.begin(), vector1.end(), generate);std::cout << "vector1:  ";std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));std::cout << std::endl;//2) 用 compare 的内容复制构造比较函数对象 comp 。值初始化底层容器 c 。std::priority_queue<Cell> queue2(std::less<Cell>(), vector1);queuePrint("queue2:   ", queue2);std::cout << std::endl;//4) 用 std::move(cont) 移动构造底层容器 c 。//以 compare 的内容复制构造比较函数对象 comp 。//调用 std::make_heap(c.begin(), c.end(), comp) 。std::priority_queue<Cell> queue4(std::less<Cell>(), std::move(vector1));queuePrint("queue4:   ", queue4);std::cout << std::endl;//5) 复制构造函数。以 other.c 的内容复制构造底层容器。以 other.comp 复制构造比较函数对象。std::priority_queue<Cell> queue5(queue2);queuePrint("queue5:   ", queue5);std::cout << std::endl;//6) 移动构造函数。以 std::move(other.c) 构造底层容器。//以 std::move(other.comp) 构造比较函数对象。std::priority_queue<Cell> queue6(std::move(queue2));queuePrint("queue6:   ", queue6);std::cout << std::endl;std::vector<Cell> vector2(6);std::generate(vector2.begin(), vector2.end(), generate);std::cout << "vector2:  ";std::copy(vector2.begin(), vector2.end(), std::ostream_iterator<Cell>(std::cout, " "));std::cout << std::endl;//13) 从 cont 复制构造 c 并从 compare 复制构造 comp 。//然后调用 c.insert(c.end(), first, last);//再调用 std::make_heap(c.begin(), c.end(), comp);std::priority_queue<Cell> queue7(vector2.begin(), vector2.end());queuePrint("queue7:   ", queue7);std::cout << std::endl;return 0;
}

输出