当前位置 博文首页 > stack和queue容器适配器_lhn的博客:C++

    stack和queue容器适配器_lhn的博客:C++

    作者:[db:作者] 时间:2021-09-22 16:55

    1、stack

    • stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。
    • stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。
    • stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:empty、back、push_back、pop_back
    • 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,默认情况下使用deque。

    stack使用

    • stack()
    • empty()
    • size()
    • top()
    • push()
    • pop()
    #include<iostream>
    #include<stack>
    
    using namespace std;
    
    int main()
    {
    	stack<int> s;
    	for(size_t i = 0; i < 10; ++i)
    	{
    		s.push(i);
    	}
    	size_t len = s.size();
    	while(len--)
    	{
    		cout<<s.top()<<endl;
    		s.pop();
    	}
    	return 0;
    }
    

    2、queue

    • 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。
    • 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素,元素从队尾入队列,从队头出队列。
    • 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:empty、size、front、back、push_back、pop_front
    • 标准容器类deque和list满足了这些要求,默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。

    queue使用

    • queue()
    • empty()
    • size()
    • front()
    • back()
    • push()
    • pop()
    #include<iostream>
    #include<queue>
    
    using namespace std;
    
    int main()
    {
    	queue<int> q;
    	for(size_t i = 0; i < 10; ++i)
    	{
    		q.push(i);
    	}
    	size_t len = q.size();
    	while(len--)
    	{
    		cout<<q.front()<<endl;
    		//cout<<q.back()<<endl;
    		q.pop();
    	}
    	return 0;
    }
    

    3、priority_queue

    优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。
    注:默认情况下priority_queue是大堆

    priority_queue使用

    • priority_queue()/priority_queue(first, last)
    • empty()
    • top():返回堆顶元素
    • push(x)
    • pop():删除堆顶元素
    #include<iostream>
    #include<queue>
    
    using namespace std;
    
    int main()
    {
    	priority_queue<int> pq;
    	pq.push(23);
    	pq.push(98);
    	pq.push(56);
    	pq.push(14);
    	pq.push(33);
    	cout<<pq.top()<<endl;
    	pq.pop();
    	cout<<pq.top()<<endl;
    	return 0;
    }
    

    4、容器适配器

    适配器
    适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该中模式是将一个类的接口转换成客户希望的另外一个接口。

    容器适配器stack、queue、priority_queue
    虽然stack、queue、priority_queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为每个容器在底层都有自己的实现方式,而stack、queue、priority_queue只是在底层将其他容器进行了封装。

    std::stack
    template<class T, class Container = deque<T>>
    class stack;
    
    std::queue
    template<class T, class Container = deque<T>>
    class queue;
    
    std::priority_queue
    template<class T, class Container = vector<T>,
    	class Compare = less<typename Container::value_type>>
    class priority_queue;
    

    为什么选择deque作为stack和queue的底层默认容器?

    stack是后进先出的特殊线性数据结构,只要具有push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,比如vector和list都可以;

    queue是先进先出的特殊线性数据结构,只要具有push_back()和pop_front()操作的线性结构,都可以作为queue的底层容器,比如list。

    但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

    • stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。
    • 在stack中元素增长时,deque比vector的效率高。
    • 在queue中的元素增长时,deque不仅效率高,而且内存使用率高。

    5、模拟实现

    • stack
    #include<iostream>
    #include<deque>
    
    using namespace std;
    
    namespace mystd
    {
    	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;
    	};
    }
    
    int main()
    {
    	mystd::stack<int> s;
    	for(size_t i = 0; i < 10; ++i)
    	{
    		s.push(i);
    	}
    	cout<<s.size()<<endl;
    	cout<<s.empty()<<endl;
    	cout<<s.top()<<endl;
    	s.pop();
    	s.pop();
    	cout<<s.size()<<endl;
    	cout<<s.empty()<<endl;
    	cout<<s.top()<<endl;
    	return 0;
    }
    
    • queue
    #include<iostream>
    #include<deque>
    
    using namespace std;
    
    namespace mystd
    {
    	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;
    	};
    }
    
    int main()
    {
    	mystd::queue<int> q;
    	for(size_t i = 0; i < 10; ++i)
    	{
    		q.push(i);
    	}
    	cout<<q.back()<<endl;
    	cout<<q.front()<<endl;
    	cout<<q.size()<<endl;
    	cout<<q.empty()<<endl;
    	q.pop();
    	q.pop();
    	cout<<q.back()<<endl;
    	cout<<q.front(
    
    下一篇:没有了