c++11 standard template (STL) (std::priority_queue) (2)

Adapt a container to provide a priority queue
std::priority_queue

Defined in the header file <queue>

template<

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

> class priority_queue;

priority_queue is a container adapter that provides constant-time (default) maximum element lookup, logarithmic cost insertion and extraction.

The order can be changed with a user-supplied Compare, eg with std::greater<T> will cause the smallest element to appear as top().

Working with priority_queue is similar to managing the heap in some random access container, with the advantage that it is impossible to invalidate the heap suddenly.

template parameter

T - The stored element type. The behavior is undefined if Tand Container::value_typeis not the same type. (since C++17)
Container - The underlying container type used to store elements. A container must meet the requirements of a sequence container (SequenceContainer), and its iterator must meet the requirements of a legacy random access iterator (LegacyRandomAccessIterator). Additionally, it must provide the following functions with the usual semantics:
  • front()
  • push_back()
  • pop_back()

The standard containers std::vector and std::deque meet these requirements.

Compare - Provides a strict and weakly ordered comparison (Compare) type.

Note that the Compare parameter is defined such that it returns true if its first argument precedes its second argument in weak ordering. But because priority_queue outputs the largest element first, the "first come" element is actually output last. That is, the head of the queue contains the "last" element in the weak ordering imposed by Compare.

member function

Construct priority_queue

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

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

(1) (since C++11)

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

(2) (since C++11)

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

(3) (until C++11)

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

(since C++11)

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

(4) (since C++11)

priority_queue( const priority_queue& other );

(5)

priority_queue( priority_queue&& other );

(6) (since C++11)

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

(7) (since C++11)

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

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

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

                const Alloc& alloc );
(9) (since C++11)
template< class Alloc >

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

                const Alloc& alloc );
(10) (since C++11)

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

(11) (since C++11)

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

(12) (since 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;
}

输出

 

Guess you like

Origin blog.csdn.net/qq_40788199/article/details/130332645
Recommended