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

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 Comparechanged , eg with std::greater<T> will cause the smallest element to appear as top().

priority_queueWorks similarly to managing the heap in some random-access container, with the advantage that it is impossible to suddenly invalidate the heap.

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.

element access

Access the top element of the stack

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

const_reference top() const;

Returns a reference to the top element of priority_queue. This element will be removed when pop() is called. If the default comparison function is used, the returned element is also the largest element in the priority queue.

parameter

(none)

return value

A reference to the top element, as obtained by calling c.front().

the complexity

constant.

modifier

Insert elements and sort the underlying container

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

void push( const value_type& value );

void push( value_type&& value );

(since C++11)

 Push the given element valueinto the priority_queue.

1) Equivalently call c.push_back(value); std::push_heap(c.begin(), c.end(), comp);

2) Equivalently call c.push_back(std::move(value)); std::push_heap(c.begin(), c.end(), comp);

parameter

value - the element value to push

return value

(none)

the complexity

Logarithmic comparison plus the complexity of Container::push_back.

remove the top element of the stack

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

void pop();

Remove the top element from priority_queue. Equivalently calls std::pop_heap(c.begin(), c.end(), comp); c.pop_back(); .

parameter

(none)

return value

(none)

the complexity

Logarithmic comparison plus the complexity of Container::pop_back.

exchange content

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

void swap( priority_queue& other ) noexcept(/* see below */);

(since C++11)

Swaps the content otherof . Equivalently calls using std::swap; swap(c, other.c); swap(comp, other.comp); .

parameter

other - The container adapter to swap content with

return value

(none)

example

noexcept specifies:  

noexcept(noexcept(swap(c, other.c)) && noexcept(swap(comp, other.comp)))

In the above expression, the identifier is looked up in the same way as used by the C++17 std::is_nothrow_swappable attribute swap.

(before C++17)
noexcept specifies:  

noexcept(std::is_nothrow_swappable<Container>::value && std::is_nothrow_swappable<Compare>::value)

(since C++17)

the complexity

Same as the underlying container (typically a constant).

call example

#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;
    };

    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) 以 cont 的内容复制构造底层容器 c 。
    std::priority_queue<Cell> queue1(std::less<Cell>(), vector1);

    while (!queue1.empty())
    {
        //返回到 priority_queue 顶元素的引用。
        //此元素将在调用 pop() 时被移除。
        //若使用默认比较函数,则返回的元素亦为优先队列中最大的元素。
        //const_reference
        std::cout << "queue1.front() before: " << queue1.top() << " ";
        //从 queue 移除顶元素。等效地调用 c.pop_back()
        queue1.pop();
        std::cout << std::endl;
    }
    std::cout << std::endl;

    std::priority_queue<Cell> queue2;
    int index = 0;
    while (index < 6)
    {
        Cell cell = generate();
        if (queue2.size() % 2 == 0)
        {
            //推给定的元素 value 到 queue 尾。
            //1) 等效地调用 c.push_back(value)
            queue2.push(cell);
        }
        else
        {
            //推给定的元素 value 到 queue 尾。
            //2) 等效地调用 c.push_back(std::move(value)),移动语义
            queue2.push(std::move(cell));
        }
        std::cout << "queue2.top() : " << queue2.top() ;
        queue2.pop();
        std::cout << std::endl;
        index++;
    }
    std::cout << std::endl;

    std::priority_queue<Cell> queue3;
    index = 0;
    while (index < 6)
    {
        int n = std::rand() % 10 + 110;
        //推入新元素到 queue 结尾。原位构造元素,即不进行移动或复制操作。
        //以与提供给函数者准确相同的参数调用元素的构造函数。
        //等效地调用 c.emplace_back(std::forward<Args>(args)...);
        queue3.emplace(n, n);
        std::cout << "queue3.front() : " << queue3.top() ;
        std::cout << std::endl;
        queue3.pop();
        index++;
    }
    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;
    std::vector<Cell> vector3(6);
    std::generate(vector3.begin(), vector3.end(), generate);
    std::cout << "vector3:  ";
    std::copy(vector3.begin(), vector3.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << std::endl;

    std::priority_queue<Cell> queue4(std::less<Cell>(), vector2);
    std::priority_queue<Cell> queue5(std::less<Cell>(), vector3);
    std::cout << "swap before:  " << std::endl;
    queuePrint("queue4:   ", queue4);
    queuePrint("queue5:   ", queue5);
    //交换容器适配器与 other 的内容。
    //等效地调用 using std::swap; swap(c, other.c);
    queue4.swap(queue5);
    std::cout << "swap after:  " << std::endl;
    queuePrint("queue4:   ", queue4);
    queuePrint("queue5:   ", queue5);

    return 0;
}

output

 

Guess you like

Origin blog.csdn.net/qq_40788199/article/details/130354208