STL的stack和queue

stack和queue

在这里插入图片描述在这里插入图片描述
这里stack和queue与其他的容器就有些区别了,前面的string,vector,list他们的模板参数传的都是空间配置器(class Alloc = allocator),这里传的是class Container=deque(deque双端队列),这说明一个问题,栈和队列严格意义上不属于容器了,而是容器适配器(通过容器转换出来的)

stack中的一些接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7IExFIlO-1653467075759)(C:/Users/yangyr0206/AppData/Roaming/Typora/typora-user-images/image-20220518172312592.png)]

queue的一些接口

在这里插入图片描述

模拟实现

适配器模式(配接器模式)

  • 什么是适配器

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

  • stack的模拟实现为了让其更适配它的模板参数是这样的

    template<class T,class Container = deque<T>>
    class stack
    {};
    
  • queue的模拟实现的模板参数与stack相同,只不过这里不适合vector了(vector不适合频繁的头插头删,时间复杂度太高)

    template<class T,class Container = deque<T>>
    class queue
    {};
    
  • 其他接口的实现主要就是靠复用其他容器的函数,根据其特性来实现即可

    namespace yyr
    {
    	template<class T,class Container=deque<T>>
    	class stack 
    	{
    	public:
    		stack(const Container& tmp=Container())
    			:st(tmp)
    		{}
    		void push(const T& val)
    		{
    			st.push_back(val);
    		}
    		void pop()
    		{
    			st.pop_back();
    		}
    		T& top()
    		{
    			return st.back();
    		}
    		const T& top() const
    		{
    			return st.back();
    		}
    		bool empty() const
    		{
    			return st.empty();
    		}
    		size_t size() const
    		{
    			return st.size();
    		}
    	private:
    		Container st;
    	};
    
    
    	//这样实现的queue不支持没有头插的容器,比如vector,不过这也符合情况
    	//队列需要频繁的头插头删,如果使用vector那么时间复杂度将会非常高
    	template<class T, class Container = deque<T>>
    	class queue
    	{
    	public:
    		queue(const Container& tmp = Container())
    			:qu(tmp)
    		{}
    		void push(const T& val)
    		{
    			qu.push_front(val);
    		}
    		void pop()
    		{
    			qu.pop_front();
    		}
    		T& front()
      		{
      			return qu.front();
      		}
      		const T& front() const
      		{
      			return qu.front();
      		}
      		T& back()
      		{
      			return qu.back();
      		}
      		const T& back() const
      		{
      			return qu.back();
      		}
    		bool empty() const
    		{
    			return qu.empty();
    		}
    		size_t size() const
    		{
    			return qu.size();
    		}
    	private:
    		Container qu;
    	};
    }
    

deque

这里对deque进行一个简单的介绍deque是一个双端队列,它是一种双向开口的连续线性空间,所谓双向开口就是可以在头尾两端分别做元素的插入和删除操作,vector虽然也可以头尾两端操作,但是头部操作效率奇差不推荐使用,deque和vector最大的区别就是deque可以进行O(1)的插入删除,而且deque没有所谓容量观念,它是动态地以分段连续空间组合而成(需要中控器来维护),虽然deque也提供了随机访问的迭代器,但是并不是普通的指针,它的迭代器组成十分的复杂。对deque进行排序操作,为了高效率可以将deque中的元素拷到vector中排序完成后再拷贝回来。(图来自于侯捷老师的STL源码剖析)
在这里插入图片描述

map(这里的map不是STL里面的map)就可以理解为一个中控的指针数组,他存放的是一段一段的buffer,而buffer里面存放的就是我们所储存的数据
在这里插入图片描述

deque作为stack和queue的默认模板参数的优势
  • 在stack中,deque对比于vector的优势

    扩容代价不大,不需要拷贝数据,浪费的空间不多,如果是vector当插入的数据刚好超出容量不多,是很浪费空间的

  • 在stack/queue中,deque对比于list的优势

    CPU高速cache命中率高。其次不会频繁的申请小块空间,申请和释放空间次数少代价低

总结:

deque作为stack和queue的默认容器是完胜的,它很适合在头尾进行插入删除,但是中间插入删除和随机访问都差强人意,所以要高频随机访问还是需要vector,要任意位置的插入删除还是需要list,deque并不能去替代vector或者list

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值