当前位置: 首页 > article >正文

c++ std::stack总结

概念

std::stack 是 C++ 标准库中的一个容器适配器(Container Adapter)。它通常是基于其他容器(如 std::dequestd::vector)实现的,提供了一个后进先出(LIFO,Last In First Out)的元素访问顺序。栈只能在栈顶(top)进行插入和删除操作,因此它只暴露了有限的接口,操作简单高效。

特点

  • 后进先出(LIFO):栈总是从栈顶访问元素,栈顶的元素总是最新的。

  • 动态大小:栈的大小可以动态增长和缩小,当有元素压入或弹出时栈的大小会相应改变。

  • 封装性强std::stack 不允许直接访问底层容器的数据(除了栈顶元素),保证了栈操作的封装性。

成员函数

  1. push(): 向栈顶插入元素。
stack.push(value);  // 将元素 value 压入栈顶
  1. pop(): 弹出栈顶元素。
stack.pop();  // 移除栈顶元素
  1. top(): 获取栈顶元素,但不移除它。
stack.top();  // 返回栈顶元素
  1. empty(): 检查栈是否为空。
stack.empty();  // 如果栈为空返回 true,否则返回 false
  1. size(): 返回栈中的元素数量。
stack.size();  // 返回栈的元素数量

底层容器

std::stack 是一个容器适配器,意味着它依赖于底层容器来存储数据。默认情况下,std::stack 使用 std::deque 作为底层容器,也可以显式选择使用 std::vectorstd::list

std::stack 是一个模板类,它可以接受两个模板参数:

  1. 元素类型(T:栈中存储的元素类型。
  2. 底层容器类型(Container:用于存储元素的底层容器类型,默认是 std::deque<T>

第二个参数允许我们指定底层容器,如 std::vectorstd::list底层容器必须支持以下操作:

  • push_back()
  • pop_back()
  • back()
  • empty()
  • size()

示例一:常规用法

#include <iostream>
#include <stack>

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

    // 向栈中压入元素
    s.push(10);
    s.push(20);
    s.push(30);

    // 输出栈顶元素
    std::cout << "Top element: " << s.top() << std::endl;  // 输出 30

    // 弹出栈顶元素
    s.pop();
    
    // 输出新的栈顶元素
    std::cout << "New top element: " << s.top() << std::endl;  // 输出 20

    // 检查栈是否为空
    if (s.empty()) {
        std::cout << "The stack is empty" << std::endl;
    } else {
        std::cout << "The stack is not empty" << std::endl;  // 输出栈不为空
    }

    // 输出栈的大小
    std::cout << "Stack size: " << s.size() << std::endl;  // 输出 2

    return 0;
}

示例二:使用 std::vector作为底层容器

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

int main() {
    // 使用 std::vector 作为底层容器
    std::stack<int, std::vector<int>> s;

    s.push(10);
    s.push(20);
    s.push(30);

    // 输出栈顶元素
    std::cout << "Top element: " << s.top() << std::endl;  // 输出 30

    s.pop();

    std::cout << "New top element: " << s.top() << std::endl;  // 输出 20
    std::cout << "Stack size: " << s.size() << std::endl;      // 输出 2

    return 0;
}

示例三:使用 std::list作为底层容器

#include <iostream>
#include <stack>
#include <list>

int main() {
    // 使用 std::list 作为底层容器
    std::stack<int, std::list<int>> s;

    s.push(100);
    s.push(200);
    s.push(300);

    // 输出栈顶元素
    std::cout << "Top element: " << s.top() << std::endl;  // 输出 300

    s.pop();

    std::cout << "New top element: " << s.top() << std::endl;  // 输出 200
    std::cout << "Stack size: " << s.size() << std::endl;      // 输出 2

    return 0;
}

示例四:自定义容器

#include <iostream>
#include <stack>
#include <deque>

// 自定义容器(必须支持 push_back, pop_back, back, size, empty)
template<typename T>
class CustomContainer {
private:
    std::deque<T> data;  // 使用 deque 存储数据
public:
    void push_back(const T& value) { data.push_back(value); }
    void pop_back() { data.pop_back(); }
    T& back() { return data.back(); }
    const T& back() const { return data.back(); }
    bool empty() const { return data.empty(); }
    size_t size() const { return data.size(); }
};

int main() {
    // 使用自定义容器作为底层容器
    std::stack<int, CustomContainer<int>> s;

    s.push(42);
    s.push(84);
    s.push(126);

    std::cout << "Top element: " << s.top() << std::endl;  // 输出 126

    s.pop();

    std::cout << "New top element: " << s.top() << std::endl;  // 输出 84
    std::cout << "Stack size: " << s.size() << std::endl;      // 输出 2

    return 0;
}

适用场景

  • 表达式求值(后缀表达式,逆波兰表示法):栈常用于计算后缀表达式或中缀表达式的转换。

  • 括号匹配:栈常用于检查表达式中的括号是否匹配。

  • 深度优先搜索(DFS):在图的遍历中,栈用于模拟递归的调用栈。

  • 回溯算法:栈可以用于回溯算法的状态追踪。

  • 撤销操作:栈可用于实现撤销操作的功能,在需要回退到上一步的场景中非常有用。

性能

  • 时间复杂度push()pop()top()empty()size() 操作都是常数时间 O(1)。

  • 空间复杂度std::stack 使用底层容器存储数据,因此其空间复杂度取决于底层容器的实现(std::dequestd::vector)。

总结

std::stack 是一个非常简单且高效的容器适配器,适合处理需要后进先出(LIFO)顺序的场景。它提供了基本的栈操作:压栈、弹栈、查看栈顶元素、检查栈是否为空等。它常用于表达式求值、图的遍历、括号匹配等实际问题。


http://www.kler.cn/a/405968.html

相关文章:

  • Web 入门
  • 【机器学习】——朴素贝叶斯模型
  • UCI Heart Disease Data Set—— UCI 心脏病数据集介绍
  • Parker派克防爆电机在实际应用中的安全性能如何保证?
  • Wallpaper壁纸制作学习记录03
  • 算法.图论-习题全集(Updating)
  • 深入理解 prompt提示词 原理及使用技巧
  • ElasticSearch7.x入门教程之中文分词器 IK(二)
  • Python操作neo4j库py2neo使用之创建和查询(二)
  • ubuntu pytorch容器内安装gpu版本的ffmpeg
  • android studio无法下载,Could not GET xxx, Received status code 400
  • C++设计模式介绍
  • Bug:引入Feign后触发了2次、4次ContextRefreshedEvent
  • IDEA 下载源码很慢,Download Source使用阿里云镜像仓库
  • 算法编程题-排序
  • 什么是Web3D?有何优势?有哪些应用场景?
  • javascrip页面交互
  • 基于 MONAI 的 3D 图像分割任务1(数据增强可视化)
  • STL容器之priority_queue的常用功能和操作
  • 初识Linux · 信号处理 · 续
  • 区块链安全常见的攻击——不安全的 Delegatecall 漏洞(Unsafe Delegatecall Vulnerability)【3】
  • 类和对象( 中 【补充】)
  • 关于xftp7 的中文乱码问题
  • C语言执行Lua进行错误处理
  • FPGA 14 ,硬件开发板分类详解,FPGA开发板与普通开发板烧录的区别
  • 优化 Spring Boot 性能