C++ STL : 模拟实现STL中的容器适配器stack和queue


什么是容器适配器

之前模拟实现的vector,string,list等都是容器,而这次要实现的stack和queue则是容器适配器,那么什么是容器适配器呢?
适配器其实就是一个转换装置,这种东西在生活中非常常见。例如将USB接口转为Type-c接口,就可以在手机上用U盘,又或者三脚插头转二脚插头,方便使用更多的插座。适配器的作用就是在不更换设备的情况下,能让我们的设备适用于其他情景,或者拥有别的功能。
在STL中,stack和queue其实就是传统数据结构中的栈和队列,我们并不关心他的底层是什么,因为我们只需要保证他具有后进先出和先进先出的特点即可,这个特点,无论是使用vector,还是list都可以实现,既然这样,那就干脆将其作为一个适配器,不需要再创建新的容器,而是直接在原有的容器上实现他的特性即可,并且这个容器可以有多种选择。


stack

stack的文档介绍-(来自cplusplus)

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

stack的实现

stack的实现其实就是栈的实现,只需要在复用原有代码的基础上增加stl的特性即可,
下面是之前数据结构篇章时实现的栈
栈的实现

库中默认选择的容器是deque

#include<deque>

namespace lee
{
	/*
		STL底层中的容器选择的是deque,因为deque是假想的连续空间,他每次插入时扩容都会直接在插入的地方直接插入一片固定大小的空间,
		这样就保证了逻辑上的线性,不需要拷贝数据。而vector每次扩容,都需要创建新空间,拷贝原数据,销毁原空间,并且开的空间是原数据的1.5倍或2倍(不同版本)
		vector不仅效率不比deque高,空间的利用率也不高,多次扩容会导致空间的碎片化
	*/

	template<class T, class Container = std::deque<T>>
	class stack
	{
	public:
		void push(const T& val)
		{
			_con.push_back(val);
		}

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

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

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

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

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

	private:
		Container _con;
	};
}

queue

queue的文档介绍-(来自cplusplus)

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

queue的实现

队列的实现

库中默认选择的容器是deque

#include<deque>

namespace lee
{
	/*
	STL中queue底层的容器是deque,因为deque和list一样插入删除的效率都是O(1),并且deque的效率更高,因为list是一次创建一个结点后插入,并且这些空间是离散分布的.
	deque是每次创建一个固定大小的空间,并在这块空间上面进行插入删除,这样的效率更高,并且因为申请的空间都是一段一段的连续空间,内存的利用率更高
	*/
	
	template<class T, class Container = std::deque<T>>
	class queue
	{
	public:
		void push(const T& val)
		{
			_con.push_back(val);
		}

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

		T& front()
		{
			return _con.front();
		}

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

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

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

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

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

	private:
		Container _con;
	};
}

猜你喜欢

转载自blog.csdn.net/qq_35423154/article/details/106497926