C ++: Understanding container adapters

What is an adapter

Adapter is a design pattern (design pattern is a set of repeated use, most people know, classified catalog, code design experience summary), the pattern is to convert a class interface into another interface that the customer wants .
Insert picture description here

Why are stack, queue and priority_queue called container adapters

Although stack, queue, and priority_queue can also store elements, they are not divided in the ranks of containers in STL, but are called container adapters , because each container has its own implementation at the bottom, And stack, queue, priority_queue just encapsulate other containers at the bottom, such as:

Insert picture description here
Insert picture description here
Insert picture description here

Simulation implementation stack, queue, priority_queue

Code example:

namespace bit
{
#include<deque>
    template<class T, class Con = deque<T>>
    class stack
    {
    public:
        stack() 
        {}

        void push(const T& x) 
        { 
            _c.push_back(x); 
        }

        void pop() 
        { 
            _c.pop_back(); 
        }

        T& top() 
        { 
            return _c.back(); 
        }

        const T& top()const 
        { 
            return _c.back(); 
        }

        size_t size()const 
        { 
            return _c.size(); 
        }

        bool empty()const 
        { 
            return _c.empty(); 
        }
    private:
        Con _c;
    };
}

namespace bit {
#include<deque>
    template<class T, class Con = deque<T>>
    class queue
    {
    public:
        queue() 
        {}

        void push(const T& x) 
        { 
            _c.push_back(x); 
        }

        void pop() 
        { 
            _c.pop_front(); 
        }

        T& back() 
        { 
            return _c.back(); 
        }

        const T& back()const 
        { 
            return _c.back(); 
        }

        T& front() 
        { 
            return _c.front(); 
        }
        
        const T& front()const 
        { 
            return _c.front(); 
        }

        size_t size()const 
        { 
            return _c.size(); 
        }

        bool empty()const 
        { 
            return _c.empty(); 
        }
    private:
        Con _c;
    };
}

namespace bit
{
    template <class T, class Sequence = vector<T>, class Compare = less<T> >
    class priority_queue
    {
    public:
        priority_queue() : c()
        {}

        template <class InputIterator>
        priority_queue(InputIterator first, InputIterator last)
            : c(first, last)
        {
            make_heap(c.begin(), c.end(), comp);
        }

        bool empty() const 
        { 
            return c.empty(); 
        }

        size_t size() const 
        { 
            return c.size(); 
        }

        T& top() const 
        { 
            return c.front(); 
        }

        void push(const T & x)
        {
            c.push_back(x);
            push_heap(c.begin(), c.end(), comp);
        }

        void pop() {
            pop_heap(c.begin(), c.end(), comp);
            c.pop_back();
        }
    private:
        Sequence c;
        Compare comp;
    };
}

Why choose deque as the bottom default container for stack and queue

Stack is a special linear data structure of last in first out, so as long as the linear structure with push_back () and pop_back () operations can be used as the bottom container of the stack, such as vector and list; queue is a first-in first-out special Linear data structures, as long as the linear structure has push_back and pop_front operations, can be used as the underlying container of the queue, such as list. But in STL, deque is selected as the underlying container for stack and queue by default, mainly because:

  1. Stack and queue do not need to be traversed (so stack and queue do not have iterators), only need to operate at a fixed end or both ends.
  2. When the elements in the stack grow, deque is more efficient than the vector; when the elements in the queue grow, deque is not only efficient, but also has high memory usage.

To sum up a sentence: deque grows and deletes at both ends at the fastest rate

Summary of main points:

stack queue
Default adapter and and
Optional adapter vector、list list
Need to operate push => push_back、pop => pop_back、top => back push => push_back、pop => pop_front、back => back、front=> front

priority_queue:

#include (imitation function)
default adapter: vector
default comparison method: less

Optional adapter: deque
optional comparison method: greater

#include (algorithm)

构造 => make_heap
push => push_back + push_heap
pop => pop_front + pop_heap
top => front

Functor: a class that can be used as a function by overloading the function call operator ("()")


If you have different opinions, please leave a message to discuss!

Published 152 original articles · praised 45 · 10,000+ views

Guess you like

Origin blog.csdn.net/AngelDg/article/details/105334941