模拟实现stack和queue

模拟实现stack和queue

1. 模拟实现stack

在开始之前,我们需要知道什么是设计模式:设计模式概念 目前有23种。

我们现在接触的模式有两种:适配器模式、迭代器模式

对于迭代器模式,使我们所熟知的,因为对于vector和list的模拟实现,都涉及到迭代器模式,迭代器模式将内部复杂的数据结构进行了封装,从而在上层使用中更为便捷,即不暴露底层细节,封装后提供统一的方式访问容器;而对于适配器模式:现实生活中,被称为适配器的有电源等待,因此适配器本质是已有的东西,封装转换出你想要的东西。对于stack的模拟实现,下面将用适配器转换,vector、list

当然,也可以用list替换vector,效果是相同的,同时缺省容器也要传list

namespace yj
{
    
    
	// 适配器模式/配接器
	template<class T, class Container = vector<T>>     //给缺省值,这里给的是缺省容器
	class stack
	{
    
     
	public:
		void push(const T& x)
		{
    
    
			_con.push_back(x);
		}

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

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

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

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

	private:
		Container _con;
	};
}

2. 模拟实现queue

同stack,模拟实现也是采用适配器的方式,因为stack和queue都不存在迭代器。由于queue经常头删,用vector效率低,因此这里最好使用list的适配器。

namespace yj
{
    
    
	// 适配器模式/配接器
	template<class T, class Container = deque<T>>       //vector不适合头删,效率低
	class queue
	{
    
    
	public:
		void push(const T& x)
		{
    
    
			_con.push_back(x);
		}

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

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

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

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

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

	private:
		Container _con;
	};
}

3. deque的介绍

3.1 deque的原理介绍

deque(双端队列)是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。

在这里插入图片描述

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示:

在这里插入图片描述

双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示:

在这里插入图片描述

那deque是如何借助其迭代器维护其假想连续的结构呢?

在这里插入图片描述

简单来说就是这样一种结构:

在这里插入图片描述

2. deque的优缺点

在这里插入图片描述

查文档发现,虽然stack和queue用了适配器模式,但是C++库中并不是vector和list,而是deque作为缺省容器这也就对应了deque的优点

优点

  1. 相比vector,扩容代价低
  2. 头插头删,尾插尾删的效率高
  3. 也支持随机访问

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

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

缺点

  1. 中间插入元素很麻烦

  2. 没有vector和list优点极致

中间插入:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Ryujianli/article/details/129573041