【c++】【STL】stack类、queue类、deque类详解及模拟

🪐🪐🪐欢迎来到程序员餐厅💫💫💫

         今日主菜:stack和queue,deque类

                 主厨:邪王真眼

            所属专栏:c++专栏

              主厨的主页:Chef‘s blog

这可是我和c++之间让人热血沸腾的组合技啊!


[本节目标]

  • 1.容器适配器

  • 2. stack的介绍和模拟

  • 3. queue的介绍和模拟

  • 4.deque的介绍

1. 容器适配器

适配器是一种设计模式 ( 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结) 该种模式是将一个类的接口转换成客户希望的另外一个接口
虽然 stack queue 中也可以存放元素, 但在STL中并没有将其划分在容器的行列 ,而是将其称为 容器适配器 ,这是因为 stack 和队列只是对其他容器的接口进行了包装,

2. stack的介绍和模拟

2.1 stack的介绍

1. stack是一种容器适配器,专门用在具有后进先出(FILO)操作的环境中,其删除只能从容器的一端进行元素的插入与提取操作。

2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。

3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:

  • empty:判空操作
  • back:获取尾部元素操作
  • push_back:尾部插入元素操作
  • pop_back:尾部删除元素操作

4. 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器, 默认情况下使用deque

我们先用vector来模拟一下

2.2 成员变量

注意事项:

         我们用的是模板,第一个参数表示数据类型,第二个表示stack是对哪个容器的封装

template<class T, class container = vector<T >>
class stack
{
public:
	//函数
private:
	container _con;
};

2.3 构造函数:

这个不用写,因为自动生成的默认构造函数会去调用container对应的容器的默认构造,这里就是vectro的默认构造。

2.4empty

是否为空栈

bool empty()
{
	return _con.empty;
}

2.5size

栈中的元素个数

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

2.6top

获取栈顶元素,注意返回值是传引用

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

2.7push

将某个元素入栈

void push(T& val)
{
	_con.push_back(val);
}

2.8pop

将栈顶弹出

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

三:queue的介绍和模拟

3.1 queue的介绍

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

 

我们先用vector来模拟一下

 

 3.2成员变量

template<class T, class container = vector<T>>
class queue
{
public:
	// 函数
private:
	container _con
};

3.3 构造函数:

这个不用写,因为自动生成的默认构造函数会去调用container对应的容器的默认构造,这里就是vectro的默认构造。

3.4empty

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

3.5size

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

3.6front

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

3.7back

两个重载就不用我多说了吧

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

3.8push

void push(T& val)
{
	_con.push_back(val);
}

3.9pop

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

四:deque的介绍

4.1 deque的原理介绍

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

4.2 deque的底层结构

deque 并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际 deque 类似于一个动态的二维 数组 ,其底层结构如下图所示:
一开始在中间开辟空间,随后根据需求向两边进行扩容

4.3deque的迭代器

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

4.4deque的缺陷与优势

优势:

  • vector比较deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是必vector高的。
  • list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。

劣势:

  • 但是,deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下
  • 中间元素插入删除时间复杂度高

简单来说,他的规避了vector和list的劣势,他的劣势是没有vector和list那么极端的优势(如vector的随机访问,list的插入删除)。

4.45为什么选择deque作为stackqueue的底层默认容器

stack 是一种后进先出的特殊线性数据结构,因此只要具有 push_back() pop_back() 操作的线性结构,都可以作为stack 的底层容器,比如 vector list 都可以; queue 是先进先出的特殊线性数据结构,只要具有push_back和 pop_front 操作的线性结构,都可以作为 queue 的底层容器,比如 list 。但是 STL 中对 stack 和queue默认选择 deque 作为其底层容器,主要是因为:
  • 1. stackqueue不需要遍历(因此stackqueue没有迭代器),只需要在固定的一端或者两端进行操作。
  • 2. stack中元素增长时,dequevector的效率高(扩容时不需要搬移大量数据)queue中的元素增长时,deque不仅效率高,而且内存使用率高。
结合了deque的优点,而完美的避开了其缺陷。

 总结:

这节课我们学了容器适配器vector、list类的模拟、deque的底层设计,看到了他迭代器的复杂应用

觉得有用的话就点个赞支持一下吧 😘😘😘

相关推荐

  1. 【LeetCode】225. 用队列实现栈(Queue接口 & Deque)

    2024-03-26 14:38:06       46 阅读
  2. Qt窗口QWidget详解

    2024-03-26 14:38:06       7 阅读
  3. 数组模板(超详细

    2024-03-26 14:38:06       5 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-26 14:38:06       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-26 14:38:06       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-26 14:38:06       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-26 14:38:06       18 阅读

热门阅读

  1. Qt源码分析:QMetaObject实现原理

    2024-03-26 14:38:06       18 阅读
  2. MongoDB 的索引有哪些 nestjs mongoose示例

    2024-03-26 14:38:06       15 阅读
  3. 在线数据格式工具

    2024-03-26 14:38:06       14 阅读
  4. 论文阅读--Offline RL Without Off-Policy Evaluation

    2024-03-26 14:38:06       14 阅读
  5. vue/js总结合集

    2024-03-26 14:38:06       16 阅读
  6. 面试算法-117-组合总和 III

    2024-03-26 14:38:06       13 阅读
  7. 缓存Caffine

    2024-03-26 14:38:06       19 阅读
  8. django关于文件分块上传的简单实现(template+view)

    2024-03-26 14:38:06       18 阅读
  9. Promise封装ajax

    2024-03-26 14:38:06       16 阅读