STL容器适配器stack和queue

Posted _Camille

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL容器适配器stack和queue相关的知识,希望对你有一定的参考价值。

STL容器适配器——stack、queue

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


前言

stack和queue是作为STL的容器适配器被实现的,容器适配器暨是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层。


一、stack

1.基本使用

先来看一下MSDN里面对stack的简单介绍示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
我们再来看一下stack简单的使用。

void main()
{
	stack<int> st;//容器适配器
	for (int i = 1; i <= 10; ++i)//将1到10顺序入栈
	{
		st.push(i);
	}
	cout << "st.size = " << st.size() << endl;
	while (!st.empty())//顺序出栈
	{
		int value = st.top();
		st.pop();
		cout << value << endl;
	}
	//无法通过迭代器访问
}	

给个题理解一下。
155.最小栈
题解:

class MinStack {
public:
    /** initialize your data structure here. */
    MinStack() 
    {}
    
    void push(int val) 
    {
        data_st.push(val);
        if(min_st.empty() || val<=min_st.top())
        min_st.push(val);
    }
    
    void pop() 
    {
        int val = data_st.top();
        data_st.pop();
        if(val == min_st.top())
            min_st.pop();
    }
    
    int top() 
    {
        return data_st.top();
    }
    
    int getMin() 
    {
        return min_st.top();
    }
private:
    stack<int> data_st;
    stack<int> min_st;
};

2.模拟实现

从栈的接口中可以看出,栈实际是一种特殊的vector,因此使用vector完全可以模拟实现stack。

namespace LJL
{
	template<class _Ty>
	class stack
	{
	public:
		stack()
		{}
		~stack()
		{}
	public:
		bool empty()const
		{
			return _C.empty();
		}
		size_t size()const
		{
			return _C.size();
		}
		_Ty& top()
		{
			return _C.back();
		}
		const _Ty& top()const
		{
			return _C.back();
		}
		void push(const _Ty &x)
		{
			_C.push_back(x);
		}
		void pop()
		{
			_C.pop_back();
		}
	private:
		vector<_Ty> _C;//若要使用list模拟只需要把vector改为list
	};
}

二、queue

1.基本使用

在这里插入图片描述
注意这里的msdn有误,队列无top一说,队列的队头为front
代码演示:

void main()
{
	queue<int> q;//容器适配器
	for (int i = 1; i <= 10; ++i)//将1到10顺序入栈
	{
		q.push(i);
	}
	cout << "q.size = " << q.size() << endl;
	while (!q.empty())//顺序出栈
	{
		int value = q.front();
		q.pop();
		cout << value << endl;
	}
	//无法通过迭代器访问
}	

在这里插入图片描述

2.模拟实现

因为queue的接口中存在头删和尾插,因此使用vector来封装的效率太低,故可以借助list来模拟实现。
代码如下:

#include <list>
namespace LJL
{
	template<class 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:
		list<T> _c;
	};
}

在系统中stack和queue是用容器双端队列deque来模拟的。

#include <deque>
namespace LJL
{
	template<class _Ty,class Cont=deque<_Ty>>
	class stack
	{
	public:
		stack()
		{}
		~stack()
		{}
	public:
		bool empty()const
		{
			return _C.empty();
		}
		size_t size()const
		{
			return _C.size();
		}
		_Ty& top()
		{
			return _C.back();
		}
		const _Ty& top()const
		{
			return _C.back();
		}
		void push(const _Ty &x)
		{
			_C.push_back(x);
		}
		void pop()
		{
			_C.pop_back();
		}
	private:
		Cont _C;
	};

	template<class _Ty, class Cont=deque<_Ty>>
	class queue
	{
	public:
		queue()
		{}
		~queue()
		{}
	public:
		bool empty()const
		{
			return _C.empty();
		}
		size_t size()const
		{
			return _C.size();
		}
		_Ty& front()
		{
			return _C.front();
		}
		_Ty& back()
		{
			return _C.back();
		}
		void pop()
		{
			_C.pop_front();
		}
		void push(const _Ty &x)
		{
			_C.push_back(x);
		}
	private:
		Cont _C;
	};
}

3.deque双端队列

是一种双开口的“连续”空间的数据结构(实际并不是连续的,而是由一段段连续的小空间拼接而成的,类似于一个动态的二维数组),可以再头尾两端进行插入和删除操作,且时间复杂度为O(1)而vector为O(n),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率较高,因为list不仅存储数据而且还需存储前后关系指针。
在这里插入图片描述

相对于普通queue而言,deque既可以尾插也可以头插,既可以头删也可以尾删。而queue只能尾插和头删。
代码演示:

void main()
{
	deque<int> dq;
	for (int i = 1; i <= 3; ++i)
	{
		dq.push_back(i);//尾插
	}
	for (int i = 3; i >= 1; --i)
	{
		dq.push_front(i);//头插
	}
	for (const auto & e : dq)
	{
		cout << e << " ";
	}
	cout << endl;
	while (!dq.empty())
	{
		cout << dq.back() << endl;
		dq.pop_back();
	}
}

在这里插入图片描述
deque的缺陷:
不适合遍历,因为在遍历时,deque的迭代器要频繁检测其是否移动到某段小空间的边界,导致效率低下,目前对于queue的应用主要为stack和queue的底层数据结构。


以上是关于STL容器适配器stack和queue的主要内容,如果未能解决你的问题,请参考以下文章

stl——容器适配器

STL容器适配器 stack, queue

STL—queue和stack使用及源码剖析

STL详解—— stack和queue的介绍及使用

[ C++ ] STL_stack(栈)queue(队列)使用及其重要接口模拟实现

[C/C++]详解STL容器3--stackqueue和priority_queue的功能和模拟实现,deque和容器适配器的介绍