C++初阶:STL详解(八)——stack和queue的介绍和使用

✨✨小新课堂开课了,欢迎欢迎~✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:C++:由浅入深篇

小新的主页:编程版小新-优快云博客

前言:

今天我们来学习stack和queue,虽然stack和queue中也可以存放元素,但在STL中并没有将其划分到容器的行列,而是将其称为容器适配器。我们来深入了解一下stack和queue吧。

一.容器适配器 

1.1什么是适配器

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

1.2STL标准库中stack和queue的底层结构

虽然 stack queue 中也可以存放元素,但在 STL 中并没有将其划分在容器的行列,而是将其称为
容器适配器 ,这是因为 stack 和queue只是对其他容器的接口进行了包装, STL stack queue 默认
使用 deque ,比如:

 1.3deque的简单介绍(了解即可)

1.3.1deque的原理介绍

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

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

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

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

1.3.2deque的缺陷

vector 比较 deque 的优势是:头部插入和删除时, 不需要搬移元素,效率特别高 ,而且在
容时,也不需要搬移大量的元素 ,因此其效率是必 vector 高的。
list 比较 ,其底层是连续空间, 空间利用率比较高 ,不需要存储额外字段。
但是, deque 有一个致命缺陷:不适合遍历,因为在遍历时, deque 的迭代器要频繁的去检测其
是否移动到某段小空间的边界,导致效率低下 ,而序列式场景中,可能需要经常遍历,因此 在实
际中,需要线性结构时,大多数情况下优先考虑 vector list deque 的应用并不多,而 目前能看
到的一个应用就是, STL 用其作为 stack queue 的底层数据结构

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

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

 元素增长时,deque不仅效率高,而且内存使用率高。

结合了deque的优点,而完美的避开了其缺陷。

总结:把deque理解成是vector和list的缝合机即可。

二.stack的介绍和使用

stack是一种容器适配器,它基于其他标准容器实现特定的数据结构行为。

特点:

1.后进先出(Last In First Out, LIFO)的数据结构。

2.只能在栈顶进行插入和删除操作。

 

栈的定义:

1.使用默认的适配器定义栈

//使用默认的适配器定义栈
stack<int> s1;

2.使用特定的适配器定义栈

//使用特定的适配器定义栈
stack<int, vector<int>> s2;

stack<int, list<int>> s3;

常用操作: 

函数说明接口说明

stack()构造空的栈

empty()检测stack是否为空

size()返回stack中元素的个数

top()返回栈顶元素的引用

push()将元素val压入stack中

pop()将stack中尾部的元素弹出

void stack01()
{
	stack<int, vector<int>> s1;

	s1.push(1);
	s1.push(2);
	s1.push(3);
	s1.push(4);//入栈

	cout << s1.size() << endl;//4

	//获取栈顶元素
	cout << s1.top() << endl;//4

	s1.pop();//删除栈顶数据

	while (!s1.empty())
	{
		cout << s1.top()<<" ";// 3 2 1
		s1.pop();
	}
	cout << endl;
	stack<int,vector<int>> s2;
	s2.push(1);
	s2.push(2);
	s2.swap(s1);//交换

	cout << s1.size() << endl;//2
	cout << s2.size() << endl;//0

}

三.queue的介绍和使用

queue是一种容器适配器,它基于其他标准容器实现特定的数据结构行为。

特点:

先进先出(First In First Out)的数据结构

只能在队尾进行插入操作,在队首进行删除操作

 queue的定义

1.使用默认的适配器定义队列

//使用默认的适配器定义队列
queue<int> q1;

2.使用特定的适配器定义队列

//使用特定的适配器定义队列
queue<int, list<int>> q2;

queue<int, vector<int>>q3;

 常用操作:

函数声明接口说明

queue()构造空的队列

empty()检测队列是否为空,是返回true,否则返回false

size()返回队列中有效元素的个数

front()返回队头元素的引用

back()返回队尾元素的引用

push()在队尾将元素val入队列

pop()将队头元素出队列
void queue01()
{
	queue<int, list<int>>q1;
	q1.push(1);
	q1.push(2);
	q1.push(3);
	q1.push(4);//入队列

	cout << q1.size() << endl;//4
	
	//获取队头元素
	cout << q1.front() << endl;//1;

    //获取队尾数据
    cout << q1.back() << endl;//4

	q1.pop();//删除队头数据

	while (!q1.empty())
	{
		cout << q1.front() << " ";//2 3 4
		q1.pop();
	}
	cout << endl;

	queue<int, list<int>> q2;
	q2.push(1);
	q2.push(2);
	q2.swap(q1);//交换

	cout << q1.size() << endl;//2
	cout << q2.size() << endl;//0

}

总结:

适配器的概念不好理解,但是我们在自己使用stack和queue的时候还是很好用的。

感谢各位大佬的观看,创作不易,还请各位大佬支持~

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值