好的!既然你提到了 C++ 标准库中的容器适配器 <stack>,我将为你详细讲解它的用法,包括基本概念、特性、功能以及实用示例。<stack> 是 C++ STL 中的一种栈容器适配器,遵循“后进先出”(LIFO, Last In First Out)的原则。它基于其他底层容器(如 <deque>)实现,提供简洁的栈操作接口。以下是完整的内容,适合学习和实践。


C++ 标准库:<stack>

<stack> 是一个模板类,封装了栈的行为。它的主要特点是:

  • LIFO 结构:元素按后进先出的顺序访问。
  • 适配器设计:基于底层容器(如 <deque><vector><list>)实现。
  • 简单接口:仅提供栈顶操作和基本管理功能。
  • 动态大小:大小随元素增减动态调整。

包含头文件

#include <stack>
#include <iostream> // 通常配合使用

定义格式

std::stack<类型, 底层容器> 变量名;
  • 类型:栈中元素的数据类型(如 intdoublestd::string)。
  • 底层容器:可选,默认是 std::deque<T>,也可以指定为 std::vector<T>std::list<T>

基本用法

1. 声明和初始化

#include <stack>
#include <iostream>

int main() {
    std::stack<int> stk; // 默认使用 deque 作为底层容器
    stk.push(1);         // 入栈
    stk.push(2);
    stk.push(3);

    std::cout << "Top: " << stk.top() << std::endl; // 输出:3
    return 0;
}
  • 不支持直接用初始化列表,需逐个 push

2. 入栈和出栈

#include <stack>
#include <iostream>

int main() {
    std::stack<int> stk;
    stk.push(10); // 入栈
    stk.push(20);
    stk.push(30);

    std::cout << "Original top: " << stk.top() << std::endl; // 输出:30
    stk.pop(); // 出栈
    std::cout << "After pop: " << stk.top() << std::endl;    // 输出:20
    return 0;
}
  • push():O(1),将元素压入栈顶。
  • pop():O(1),移除栈顶元素(不返回)。

3. 访问栈顶

#include <stack>
#include <iostream>

int main() {
    std::stack<std::string> stk;
    stk.push("Apple");
    stk.push("Banana");

    std::cout << "Top: " << stk.top() << std::endl; // 输出:Banana
    return 0;
}
  • top():O(1),返回栈顶元素的引用。
  • 无随机访问,只能访问栈顶。

4. 大小和状态

#include <stack>
#include <iostream>

int main() {
    std::stack<int> stk;
    std::cout << "Empty? " << (stk.empty() ? "Yes" : "No") << std::endl; // 输出:Yes
    std::cout << "Size: " << stk.size() << std::endl;                    // 输出:0

    stk.push(1);
    stk.push(2);
    std::cout << "Empty? " << (stk.empty() ? "Yes" : "No") << std::endl; // 输出:No
    std::cout << "Size: " << stk.size() << std::endl;                    // 输出:2
    return 0;
}
  • empty():O(1),检查栈是否为空。
  • size():O(1),返回当前元素数。

5. 指定底层容器

#include <stack>
#include <vector>
#include <iostream>

int main() {
    std::stack<int, std::vector<int>> stk; // 使用 vector 作为底层容器
    stk.push(10);
    stk.push(20);
    stk.push(30);

    std::cout << "Top: " << stk.top() << std::endl; // 输出:30
    stk.pop();
    std::cout << "New top: " << stk.top() << std::endl; // 输出:20
    return 0;
}
  • 默认用 <deque>,但可改为 <vector><list>

与其他容器的对比

特性std::stackstd::vectorstd::deque
数据结构栈(LIFO)动态数组双端队列
访问方式仅栈顶随机访问随机访问
插入/删除仅顶部 O(1)尾 O(1),其他 O(n)首尾 O(1),其他 O(n)
底层容器可选(默认 deque)自身自身
迭代器不支持支持支持

注意事项

  1. 接口限制:无迭代器,无法遍历所有元素,只能操作栈顶。
  2. 异常安全top()pop() 在空栈上调用是未定义行为,需先检查 empty()
  3. 底层容器选择
  • <deque>(默认):首尾操作高效。
  • <vector>:尾部操作高效,节省内存。
  • <list>:插入/删除高效,但内存开销大。
  1. 性能:依赖底层容器,默认 <deque> 提供最佳平衡。

实用示例:括号匹配

以下是一个经典应用:检查括号是否匹配。

#include <stack>
#include <iostream>
#include <string>

bool isValid(const std::string& s) {
    std::stack<char> stk;
    for (char c : s) {
        if (c == '(' || c == '[' || c == '{') {
            stk.push(c);
        } else if (c == ')' || c == ']' || c == '}') {
            if (stk.empty()) return false;
            char top = stk.top();
            stk.pop();
            if ((c == ')' && top != '(') ||
                (c == ']' && top != '[') ||
                (c == '}' && top != '{')) {
                return false;
            }
        }
    }
    return stk.empty(); // 栈空表示匹配
}

int main() {
    std::string expr1 = "{[()]}";
    std::string expr2 = "{[}";
    std::cout << expr1 << " is " << (isValid(expr1) ? "valid" : "invalid") << std::endl;
    std::cout << expr2 << " is " << (isValid(expr2) ? "valid" : "invalid") << std::endl;
    return 0;
}

输出:

{[()]} is valid
{[} is invalid

小练习

以下是一个基于 <stack> 的练习题,你可以尝试:

问题:

写一个 C++ 程序:

  1. 定义一个 std::stack<int>
  2. 依次压入 10、20、30、40。
  3. 输出栈顶元素。
  4. 弹出两个元素。
  5. 输出剩余元素个数和栈顶元素。

参考答案(你可以先尝试)

#include <stack>
#include <iostream>

int main() {
    std::stack<int> stk;

    // 压入元素
    stk.push(10);
    stk.push(20);
    stk.push(30);
    stk.push(40);

    // 输出栈顶
    std::cout << "Top: " << stk.top() << std::endl; // 输出:40

    // 弹出两个元素
    stk.pop();
    stk.pop();

    // 输出剩余元素个数和栈顶
    std::cout << "Size: " << stk.size() << std::endl;    // 输出:2
    std::cout << "New top: " << stk.top() << std::endl;  // 输出:20

    return 0;
}

下一步

  • 如果你想试试这个练习,请写下你的代码,我会帮你检查。
  • 如果你想要更复杂的内容(如逆波兰表达式计算、自定义底层容器),或者设计 <stack> 的测验题,请告诉我!
  • 你也可以提出具体问题,如“如何用 <stack> 实现递归?”或“<stack><deque> 的区别?”。

现在,你想做什么?试试练习,还是有其他需求?