1. stack 介绍及使用方法
stack 是一种后进先出的数据结构,所以在 C++ 的 STL 库中也同样遵循了这一点,我们在使用的时候不支持随机访问或迭代器遍历。
注意事项
- 调用
top()或pop()前需确保栈非空,否则可能引发未定义行为。 stack没有clear()函数,如需清空栈需手动循环调用pop()。- 性能:所有操作的时间复杂度为 O(1)。
stack 的底层是一个 deque<T>(双端队列),虽然 deque 是可以从两端来进行操作的,但是我们只要只提供一端的接口,那么就可以来把它当做 stack 来使用。
我们在空间上要把它理解成这个样子,图示这样更好理解。

2. stack 的常用接口
| 函数名 | 作用 |
|---|---|
| void push(const T& x) | 放一个元素进入 stack |
| void pop() | 抛出一个元素 |
| T& top() | 返回最后一个放入的元素 |
| size_t size() | 返回 stack 里面的元素个数 |
| bool empty() | 判断是否为空 |
接下来我将逐一实现这些接口。
3. 模板参数说明
在这里写两个 class 是为了方便使用,这两个模板参数实际上是各司其职,只是语法上要求写在同一个 template<> 里,使用时会根据场景自动匹配对应的参数。
前面的
T是明确指定栈中元素的类型(比如int、string等),这是栈对外提供的'数据类型契约'——栈里只能存T类型的东西。后面的Container是指定用什么容器来存储这些T类型的元素,而默认的deque<T>就是'用双端队列来存T类型元素'的意思。
PS:只写后面那一个理论上来说也是可以的,但是会让用户使用门槛变高,比如想声明一个存 int 的栈,用户不能直接写 stack<int>,而必须写成 stack<deque<int>>(如果想用默认容器),或者 stack<vector<int>>。这会让接口变得不直观——用户需要先知道底层容器的类型,才能正确声明栈,违背了'栈是容器适配器,用户无需关心底层实现'的设计初衷。
PS:只写前面哪一个是不行的,如果只写 template<class T>,就意味着用户无法指定底层容器了——因为没有 Container 这个参数来接收用户自定义的容器类型。
template<class T, = deque<T>>


