【041】从零开始:逐步学习使用C++ STL中的stack容器

news2024/10/5 11:43:10

从零开始:逐步学习使用C++ STL中的stack容器

  • 引言
  • 一、stack容器概述
  • 二、stack容器常用API
    • 2.1、构造函数
    • 2.2、赋值操作
    • 2.3、数据存取操作
    • 2.4、大小操作
  • 三、使用stack容器实现一个高效的算法
  • 总结

引言


💡 作者简介:一个热爱分享高性能服务器后台开发知识的博主,目标是通过理论与代码实践的结合,让世界上看似难以掌握的技术变得易于理解与掌握。技能涵盖了多个领域,包括C/C++、Linux、Nginx、MySQL、Redis、fastdfs、kafka、Docker、TCP/IP、协程、DPDK等。
👉
🎖️ CSDN实力新星、CSDN博客专家
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【040】巧妙地穿梭双端:掌握C++ STL中deque容器的强大功能

一、stack容器概述

stack是一种先进后出(First In Last OutFILO)的数据结构,它只有一个出口,形式如图所示。stack容器允许新增元素,移除元素,取得栈顶元素,但是除了最顶端外,没有任何其他方法可以存取stack的其他元素。换言之,stack不允许有遍历行为。有元素入栈的操作称为:push,将元素推出stack 的操作称为pop。
在这里插入图片描述
Stack所有元素的进出都必须符合"先进后出"的条件,只有stack顶端的元素,才有机会被外界取用。Stack不提供遍历功能,也不提供迭代器。

二、stack容器常用API

C++的stack容器是通过<stack>头文件提供的。

  1. 构造函数:

    • stack<T> s:创建一个空的stack,其中T是数据类型。
  2. 成员函数:

    • push(const T& val):将元素val压入栈顶。
    • emplace(Args&&... args):通过参数构造一个元素并将其压入栈顶。
    • pop():移除栈顶元素。
    • top():返回栈顶元素的引用。
    • empty():检查栈是否为空,返回布尔值。
    • size():返回栈中元素的个数。
  3. 非成员函数:

    • swap(stack<T>& other):交换两个栈的内容。

stack不提供遍历功能,因为它是一种后进先出(LIFO)数据结构。

2.1、构造函数

stack容器的构造函数原型如下:

explicit stack(const Container& cont = Container());

其中,Container是可选参数,用于指定底层容器类型,默认为deque

以下是几个使用示例:

示例 1:使用默认构造函数创建空的stack

#include <iostream>
#include <stack>

int main() {
    std::stack<int> s; // 默认构造函数创建一个空的stack

    if (s.empty()) {
        std::cout << "Stack is empty!" << std::endl;
    }

    return 0;
}

示例 2:使用vector作为底层容器创建stack

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

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

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

    while (!s.empty()) {
        std::cout << s.top() << " "; // 输出栈顶元素
        s.pop(); // 弹出栈顶元素
    }
    
    return 0;
}

示例 3:使用现有容器初始化stack

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

int main() {
    std::list<int> values = {1, 2, 3, 4};

    std::stack<int, std::list<int>> s(values); // 使用现有容器初始化stack

    while (!s.empty()) {
        std::cout << s.top() << " "; // 输出栈顶元素
        s.pop(); // 弹出栈顶元素
    }

    return 0;
}

这些示例展示了如何使用stack容器的构造函数来创建空的栈或从现有容器初始化栈。可以根据需要选择不同的底层容器类型,如默认的deque或用户指定的vectorlist等。

2.2、赋值操作

可以使用std::stack模板类中的成员函数swap()来交换两个栈的内容实现赋值的效果。

swap()函数的原型如下:

void swap(stack& other);

使用示例:

#include <iostream>
#include <stack>

int main() {
    std::stack<int> stack1;
    std::stack<int> stack2;

    stack1.push(1);
    stack1.push(2);
    stack1.push(3);

    stack2.push(4);
    stack2.push(5);

    std::cout << "Stack 1: ";
    while (!stack1.empty()) {
        std::cout << stack1.top() << " "; // 输出栈1的元素
        stack1.pop();
    }
    
    std::cout << "\nStack 2: ";
    while (!stack2.empty()) {
        std::cout << stack2.top() << " "; // 输出栈2的元素
        stack2.pop();
    }

    stack1.swap(stack2); // 交换栈1和栈2的内容

    std::cout << "\nStack 1 after swapping: ";
    while (!stack1.empty()) {
        std::cout << stack1.top() << " "; // 输出交换后的栈1的元素
        stack1.pop();
    }

    std::cout << "\nStack 2 after swapping: ";
    while (!stack2.empty()) {
        std::cout << stack2.top() << " "; // 输出交换后的栈2的元素
        stack2.pop();
    }

    return 0;
}

输出:

Stack 1: 3 2 1 
Stack 2: 5 4 
Stack 1 after swapping: 5 4 
Stack 2 after swapping: 3 2 1 

以上示例中,通过调用swap()函数来交换了两个栈stack1stack2的内容。这样就实现了将一个栈的元素赋值给另一个栈的效果。

2.3、数据存取操作

std::stack容器的数据存取操作函数包括:

  • top():返回栈顶元素的引用,但不会删除该元素。
  • push(const T& value):将元素插入到栈顶。
  • pop():移除栈顶元素,没有返回值。

使用示例:

#include <iostream>
#include <stack>

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

    stack.push(1);
    stack.push(2);
    stack.push(3);

    // 访问栈顶元素
    int topElement = stack.top();
    std::cout << "Top element: " << topElement << std::endl;

    // 修改栈顶元素
    stack.top() = 4;

    // 移除栈顶元素
    stack.pop();

    std::cout << "Stack elements:";
    while (!stack.empty()) {
        std::cout << " " << stack.top();
        stack.pop();
    }
    std::cout << std::endl;

    return 0;
}

输出:

Top element: 3
Stack elements: 2 1

2.4、大小操作

std::stack容器提供了以下函数来进行大小操作:

  • empty():返回栈是否为空,如果栈为空则返回true,否则返回false
  • size():返回栈中元素的数量。

以下是这些函数的函数原型和使用示例:

#include <iostream>
#include <stack>

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

    stack.push(1);
    stack.push(2);
    stack.push(3);

    bool isEmpty = stack.empty();
    std::cout << "Is stack empty? " << (isEmpty ? "Yes" : "No") << std::endl;

    size_t stackSize = stack.size();
    std::cout << "Stack size: " << stackSize << std::endl;

    return 0;
}

输出:

Is stack empty? No
Stack size: 3

三、使用stack容器实现一个高效的算法

使用C++的stack容器实现简单算法,该算法用于判断一个字符串中的括号是否匹配。

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

bool isBracketMatching(const std::string& str) {
    std::stack<char> brackets;

    for (char ch : str) {
        if (ch == '(' || ch == '[' || ch == '{') {
            brackets.push(ch);
        } else if (ch == ')' || ch == ']' || ch == '}') {
            // 如果当前字符为右括号
            if (brackets.empty()) {
                // 栈为空,无法匹配
                return false;
            } else {
                char top = brackets.top();
                brackets.pop();

                // 判断栈顶元素与当前右括号是否匹配
                if ((top == '(' && ch != ')') ||
                    (top == '[' && ch != ']') ||
                    (top == '{' && ch != '}')) {
                    return false;
                }
            }
        }
    }

    // 所有字符遍历完成后,栈为空才说明括号全部匹配
    return brackets.empty();
}

int main() {
    std::string str1 = "({})[]"; // 匹配
    std::string str2 = "{[}]";   // 不匹配

    std::cout << "字符串1括号" << (isBracketMatching(str1) ? "匹配" : "不匹配") << std::endl;
    std::cout << "字符串2括号" << (isBracketMatching(str2) ? "匹配" : "不匹配") << std::endl;

    return 0;
}

首先,我们遍历字符串中的每个字符,如果遇到左括号('(''[''{'),我们将其压入栈中。当遇到右括号时,我们检查栈顶元素是否与当前右括号匹配,并将栈顶元素弹出。如果任何时刻栈为空、栈顶元素与当前右括号不匹配,或者遍历结束后栈仍然非空,那么就意味着括号不匹配。

main()函数中,我们测试了两个字符串的括号匹配情况,并输出相应的结果。

运行上述代码,输出:

字符串1括号匹配
字符串2括号不匹配

示例演示了如何利用C++的stack容器来实现一个简单算法,通过使用栈来追踪括号的嵌套关系,并判断括号是否匹配。这只是stack容器的一个简单应用示例,而stack还有其他更多有用的功能可以探索和利用。

总结

深入讲解了C++ STL中的stack容器的基本概念和操作。首先介绍了栈的定义和特点,然后详细解释了stack容器的创建和管理方法,包括入栈、出栈和访问栈顶元素等操作。此外,还重点探讨了stack容器的大小操作函数,并通过实例加深了对其用法的理解。通过本文的学习,读者能够全面了解如何在C++中运用stack来实现栈结构,并且能够合理地利用stack提高代码效率和可读性。无论读者是初学者还是有一定经验的开发者,本文都能帮助他们掌握使用C++ STL中的stack容器的技巧和技能,为日后的编程工作打下坚实的基础。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/768783.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安达发|如何选择更适合我们的APS高级排程软件

如何选择aps高级排程公司更适合我们?在选购aps高级排程的时候&#xff0c;一些朋友由于不清楚其中的选购技巧&#xff0c;许多时候会掉入些许选择误区&#xff0c;导致我们买不了合适我们选择的aps高级排程。因此选择适合我们的aps高级排程就变得十分重要&#xff0c;唯有明白…

23.JavaWeb-集群+Nginx+JMeter

1.集群概念 平时用的服务是的并发量是有限的&#xff0c;像tomcat只有不到500的并发量&#xff0c;不能满足高并发的需求&#xff0c;因此就采用了集群的方法&#xff0c;用多个服务器 当用户请求集群系统时&#xff0c;集群给用户的感觉就是一个单一独立的服务器&#xff0c;而…

项目中使用拆分数据库的优势

为什么要拆分数据库&#xff1f; 取决于数据库的负载和数据量。 单体项目在构建之初&#xff0c;数据库的负载和数据量都不大&#xff0c;所以不需要对数据库做拆分&#xff0c;小型财务系统、文书系统、ERP系统、OA系统&#xff0c;用一个MySQL数据库实例基本就够用了。 就…

重绘 ( Repaint) 和回流 ( Reflow)

重绘 ( Repaint) 和回流 ( Reflow) 首先了解 重绘 ( Repaint) 和回流 ( Reflow)其实是关乎到浏览器性能的问题 重绘和回流是渲染步骤中的⼀⼩节&#xff0c;但是这两个步骤对于性能影响很大 重绘和回流的过程都需要浏览器耗费大量的计算资源&#xff0c;过多的使用会导致网页性…

港联证券|熨平短期扰动 7月MLF小额加量续作

7月17日&#xff0c;为保护银行系统流动性合理充裕&#xff0c;人民银行开展1030亿元中期借贷便利&#xff08;MLF&#xff09;操作和330亿元公开商场逆回购操作,充沛满足了金融机构需求。本月MLF中标利率和公开商场逆回购操中标利率与上期持平&#xff0c;分别为2.65%、1.9%。…

[深度学习入门]什么是神经网络?[神经网络的架构、工作、激活函数]

目录 一、前言二、神经网络的架构——以手写数字识别三、神经网络的工作1、单输入单输出感知器函数2、二维输入参数3、三维输入参数 四、激活函数1、激活函数2、ReLU激活函数3、非线性激活函数&#xff08;1&#xff09;二输入二输出的神经网络的架构&#xff08;2&#xff09;…

创建、发布npm包,并且应用在项目里面

实现一个函数去监听dom宽高的变化&#xff0c;并且发布NPM包&#xff0c;然后使用到项目中 步骤 1.5W3H 八何分析法 2.如何监听dom宽高变化 3.如何用vite 打包库 4.如何发布npm 一、NPM包新建过程 查看完整目录 1.生成 package.json npm init生成TS配置文件 tsconfig.js…

OpenVas扫描器更新扫描引擎

OPenvas扫描器安装时step1 是交换指导升级&#xff08;nvt&#xff0c;cert&#xff0c;scap&#xff09;&#xff0c;这次升级后是自动升级24h升级一次&#xff0c;但第一次升级时选择默认的rsync升级时会出现同步失败的问题&#xff0c;导致openvas安装完后有很大模块和规则不…

软件测试教程之测试分类

目录 1.按测试对象分类 界面测试 可靠性测试 容错性测试 文档测试 兼容性测试 易用性测试 安装卸载测试 性能测试 安全性测试 内存泄漏测试 2.按照是否查看代码分类 黑盒测试 白盒测试 灰盒测试 3.按开发阶段划分 单元测试 集成测试 系统测试 回归测试 冒…

栈的压入、弹出序列

链接: 栈的压入、弹出序列 class Solution { public:/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可** * param pushV int整型vector * param popV int整型vector * return bool布尔型*/bool IsPopOrder(vector<int…

视频制作高清GIF动图的简单方法分享

有时想要将电视剧、电影中的精彩画面保存下来&#xff0c;但是视频较大非常的不方便的时候该怎么办呢&#xff1f;这时候&#xff0c;可以使用专业的视频转gif&#xff08;https://www.gif.cn/&#xff09;工具-GIF中文网&#xff0c;无需下载软件&#xff0c;手机、pc均可在线…

【深度学习平台推荐】 Kaggle

工欲善其事&#xff0c;必先利其器。在一个优秀的平台上&#xff0c;更利于深度学习的探究。 本文目的是推荐一些深度学习相关的网站。 1 Kaggle Kaggle offers a no-setup, customizable, Jupyter Notebooks environment. Access GPUs at no cost to you and a huge repositor…

搭建Redis主从集群和哨兵

说明&#xff1a;单机的Redis存在许多的问题&#xff0c;如数据丢失问题、高并发问题、故障恢复问题、海量数据的存储能力问题&#xff0c;针对这四个问题&#xff0c;对应解决方式有&#xff1a;数据持久化&#xff08;参考&#xff1a;http://t.csdn.cn/SSyBi&#xff09;、搭…

07-尚硅谷大数据技术之Spark源码

1. 环境准备&#xff08;Yarn 集群&#xff09; 搭建Spark on Yarn集群 3.3 Yarn 模式 独立部署&#xff08;Standalone&#xff09;模式由 Spark 自身提供计算资源&#xff0c;无需其他框架提供资源。这种方式降低了和其他第三方资源框架的耦合性&#xff0c;独立性非常强。但…

C#鼠标拖拽,移动图片实例

最近工作需要做一个鼠标可以拖拽移动图片的功能。 写了几个基本功能&#xff0c;勉强能用。这里记录一下。欢迎大神补充。 这个就是完成的功能。 下边的绿色是一个pictureBox&#xff0c;白色框也是一个pictureBox&#xff0c;他们二者是子父级关系。 绿色是父级&#xff0c…

网约车订单自助测试演进与落地实践

1► 业务背景 网约车业务作为滴滴的核心业务&#xff0c;系统架构复杂、整个订单链路涉及众多下游服务&#xff0c;整体迭代频率高&#xff0c;同时在产品形态上通过不同品类提供差异化服务能力&#xff0c;整体品类从最初的专车、快车延展到如今多个品类&#xff0c;这就导致在…

Android 分别使用Java和Kotlin给Textview设置第三方字体、APP全局字体、 Android X字体设置

前言 本文介绍Android实现全局设置自定义字体和局部设置自定义字体即单个TextView设置字体&#xff0c;同时也提供了一些优秀的三方字体框架&#xff0c;基本可以满足开发者对字体设置的全部要求。 使用自定义字体前后效果图 一、assets是什么&#xff1f; 首先需要了解Andr…

【11】STM32·HAL库开发-STM32CubeMX简介、安装 | 新建STM32CubeMX工程步骤

目录 1.STM32CubeMX简介&#xff08;了解&#xff09;2.STM32CubeMX安装&#xff08;了解&#xff09;2.1STM32CubeMX软件获取2.1.1获取Java软件2.1.2获取STM32CubeMX软件 2.2搭建Java运行环境2.3安装STM32CubeMX软件&#xff08;必须先2.2再2.3&#xff09;2.4下载和关联STM32…

若依cloud(RuoYi-Cloud)新增业务模块和功能模块增删改查演示

前言 看了几篇文章感觉都不太满意&#xff0c;索性自己来写一篇。 一、后端 后端新建业务模块流程大致如下&#xff1a; 1、后端新建一个&#xff08;在ruoyi-module模块下&#xff09;业务模块&#xff0c;仿照已有的模块将此模块配置好&#xff0c;例如仿照系统模块&…

6、PHP语法要点(1)

PHP的语法跟C语言还是类似的。 1、变量不用定义即可直接使用。 2、函数外定义的变量为全局变量。global 关键字用于函数内访问全局变量。 3、static 用于保持函数内局部变量的值。但在函数外依然不能访问。 4、PHP 将所有全局变量存储在一个名为 $GLOBALS[index] 的数组中。…