[微信公众号:Cpp入门到精通]有完整六十六节知识,STL知识总结,欢迎关注学习!!
stack是STL中的一个适配器容器,它基于其他序列容器(默认为deque)实现,提供了栈(stack)的功能。栈是一种后进先出(LIFO)的数据结构,即最后压入栈的元素最先被弹出。
我们首先讲一讲什么是容器适配器,容器适配器是建立在现有容器之上的一层抽象,提供了一种限制和修改现有容器接口的方式。容器适配器不是自己实现容器,而是通过调用底层容器的成员函数,以适应某些特定的用途。容器适配器本身不存储数据,它通常提供了一种更受限制的接口,适用于特定的用途。例如,stack 提供了栈的操作,queue 提供了队列的操作。
stack容器有以下成员函数可供操作:
1.push(data): 将元素压入栈的顶部。
stack<int>s1;
s1.push(10);
s1.push(20);
2.pop(): 弹出栈顶的元素,不返回弹出的元素。
s1.pop();
3.top(): 返回栈顶的元素,但不移除它。
cout<<"栈顶元素为:"<<s1.top();
4.empty(): 判断栈是否为空。
当栈非空的情况下,返回栈顶元素:
while (!s.empty())
{
cout << "栈顶元素为:" << s.top() << endl;
s.pop();
}
在这里我们使用pop()移除了栈顶元素,这样做的原因是:
维护栈的特性:栈的本质是一种限制在栈顶进行插入和删除操作的数据结构。通过 pop(),我们确保栈的顶部元素是最后一个被插入的,从而保持了栈的 LIFO 特性。
释放资源:如果栈中存储的是动态分配的内存或其他资源,pop() 操作可以用于释放这些资源。当不再需要栈顶的元素时,通过 pop() 可以及时释放相关资源,防止内存泄漏或其他资源泄漏问题。
5.size(): 返回栈中元素的数量。
cout << "栈的大小为:" << s.size() << endl;
stack 可以作为多种底层容器的适配器,比如说deque(双端队列,默认情况下);vector(动态数组);list(双向链表)。也可以自定义容器类型,只需确保该容器类型满足栈的基本要求,即支持 push_back()、pop_back()、back() 等操作。
当我们要把某一容器作为stack底层容器,只需要这样操作:
#include <stack>
#include <deque>
int main() {
stack<int, deque<int>> myStack;
// 在这里进行栈操作
return 0;
}
其他容器类似这样操作。
容器适配器queue
接下来我们介绍另一种容器适配器queue,它实现了队列(queue)数据结构。队列是一种先进先出(FIFO)的数据结构,即最先进入队列的元素最先被取出。
queue的基本操作有:
-
push(): 将元素推入队列尾部。
-
pop(): 弹出队列头部的元素。
-
front(): 返回队列头部的元素,但不弹出。
-
back(): 返回队列尾部的元素,但不弹出。
-
empty(): 判断队列是否为空。
-
size(): 返回队列中元素的数量。
读者可以试着操作一下。
queue可以作为deque(双端队列,默认情况下);list(双向链表)的容器适配器。而vector由于没有pop_front(),故不能作为queue的底层容器。
为了更好的区分两种容器适配器,我们作以下比较:
容器适配器 | stack | queue |
数据结构特性 | 实现了栈数据结构,采用后进先出(LIFO)的原则。只允许在栈顶进行插入和删除操作。 | 实现了队列数据结构,采用先进先出(FIFO)的原则。只允许在队尾进行插入,在队头进行删除。 |
适用场景 | 适用于需要后进先出顺序的场景,如深度优先搜索、递归函数的调用栈等。 | 适用于需要先进先出顺序的场景,如广度优先搜索、任务调度等。 |
使用方式 | 主要通过 push、pop 和 top 操作进行栈的相关操作。 | 主要通过 push、pop、front 和 back 操作进行队列的相关操作。 |
底层容器 | 通常使用deque 作为底层容器,但也可以选择其他合适的容器。 | 默认使用 deque,但同样可以选择其他容器。 |