容器适配器-stack栈
C++标准库不只是包含了顺序容器,还包含一些为满足特殊需求而设计的容器,它们提供简单的接口。
这些容器可被归类为容器适配器(container adapter),它们是改造别的标准顺序容器,使之满足特殊需求的新容器。
适配器:也称配置器,把一种接口转为另一种接口。
有三种标准的 容器适配器: stack(栈)、queue(队列)和priority queue(优先级队列)。 priority queue就是“根据排序准则,自动将元素排序”的队列,其所谓“下一个””元素总是拥有最高优先级。
stack栈
stack 栈是一种只在一端(栈顶)进行数据插入(入栈)和删除(出栈)的数据结构,它满足后进先出(LIFO)的特性。
使用push(入栈)将数据放入stack,使用pop(出栈)将元素从容器中移除。 POP PUSH栈顶TOP栈底
使用stack,必须包含头文件:
#include <stack>
在头文件中,class stack定义如下:
namespace std{template <typename T,typename Container = deque<T>>class stack;
}
第一个参数T代表类型,第二个参数用来定义stack内部存放数据的容器,默认为deque。之所以选择deque而非vector,是因为deque移除数据时可能会释放内存,并在插入数据需要扩容时不需要复制所有的数据。
例如,以下定义了一个元素类型为整数的 stack:
std::stack<int> st;
stack 只是很单纯地把各项操作转化为内部容器对应的函数调用。你可以使用任何支持 back()、push_back()和pop_back()成员函数的标准容器支持 stack。例如你可以使用 vector或list 来存放数据:
stack<int,vector<int>> st;//整型栈,使用vector存放数据
注意:forword_list和array不可以作为其容器
定义及初始化
#include <iostream>
#include <stack>
#include <vector>
#include <list>
using namespace std;int main()
{stack <char> s1;//创建一个默认的栈,最常用stack <char, deque<char> > s2;//显示创建用deque保存数据的栈,和s1等价stack <int, vector<int> > s3;//创建用vector保存数据的栈stack <int, list<int> > s4;//创建用list保存数据的栈return 0;
}
先创建一个空的栈,然后往里面存放数据。
常用操作
stack栈的操作比较简单,不支持迭代器和运算符,只有几个简单的成员函数。 empty成员函数
empty成员函数
判断栈是否为空。
//判空
bool IsEmpty(PLStack ps)
{return ps->next == NULL;
}
pop成员函数
出栈函数,删除栈顶元素。
//获取栈顶元素的值,并且删除
bool Pop(PLStack ps, int* rtval)
{assert(ps != NULL);if (ps == NULL)return false;if (IsEmpty(ps))return false;*rtval = ps->next->date;LSNode* p = ps->next;ps->next = ps->next->next;free(p);return true;
}
push成员函数
入栈函数,往栈顶添加数据。
//往栈中入数据(入栈操作)
bool Push(PLStack ps, int val)
{assert(ps != NULL);if (ps == NULL)return false;LSNode* p = (LSNode*)malloc(sizeof(LSNode));assert(p != NULL);p->date = val;p->next = ps->next;ps->next = p;return false;
}
size成员函数
返回栈的数据个数。
//获取栈中有效数据的个数
int GetLength(PLStack ps)
{assert(ps != NULL);if (ps == NULL)return 0;int count = 0;for (LSNode* p = ps->next; p != NULL; p = p->next){count++;}return count;
}
top成员函数
返回栈顶元素的引用。
//获取栈顶元素的值,但不删除
bool GetTop(PLStack ps, int* rtval)
{assert(ps != NULL);if (ps == NULL)return false;if (IsEmpty(ps))return false;*rtval = ps->next->date;return true;
}
栈的实现方式
链表实现:链表实现栈则更加灵活,它不需要预先分配固定大小的内存空间,适用于栈的大小动态变化且难以预估的场景。在链表实现中,每个节点包含数据和指向下一个节点的指针。栈顶对应链表的头节点,入栈和出栈操作都在链表头部进行,时间复杂度同样为 O (1)。
.h文件
#pragma once//链式栈
typedef struct LSNode
{int date;struct LSNode* next;
}LSNode, * PLStack;//初始化
void InitStack(PLStack ps);//往栈中入数据(入栈操作)
bool Push(PLStack ps, int val);//获取栈顶元素的值,但不删除
bool GetTop(PLStack ps, int* rtval);//获取栈顶元素的值,并且删除
bool Pop(PLStack ps, int* rtval);//判空
bool IsEmpty(PLStack ps);//获取栈中有效数据的个数
int GetLength(PLStack ps);//清空所有的数据
void Clear(PLStack ps);//销毁
void Destroy(PLStack ps);
.cpp文件
#include "Istak.h"
#include <iostream>
#include <cassert>
using namespace std;//初始化
void InitStack(PLStack ps)
{assert(ps != NULL);if (ps == NULL)return;ps->next = NULL;
}//往栈中入数据(入栈操作)
bool Push(PLStack ps, int val)
{assert(ps != NULL);if (ps == NULL)return false;LSNode* p = (LSNode*)malloc(sizeof(LSNode));assert(p != NULL);p->date = val;p->next = ps->next;ps->next = p;return false;
}//获取栈顶元素的值,但不删除
bool GetTop(PLStack ps, int* rtval)
{assert(ps != NULL);if (ps == NULL)return false;if (IsEmpty(ps))return false;*rtval = ps->next->date;return true;
}//获取栈顶元素的值,并且删除
bool Pop(PLStack ps, int* rtval)
{assert(ps != NULL);if (ps == NULL)return false;if (IsEmpty(ps))return false;*rtval = ps->next->date;LSNode* p = ps->next;ps->next = ps->next->next;free(p);return true;
}//判空
bool IsEmpty(PLStack ps)
{return ps->next == NULL;
}//获取栈中有效数据的个数
int GetLength(PLStack ps)
{assert(ps != NULL);if (ps == NULL)return 0;int count = 0;for (LSNode* p = ps->next; p != NULL; p = p->next){count++;}return count;
}//清空所有的数据
void Clear(PLStack ps)
{Destroy(ps);
}//销毁
void Destroy(PLStack ps)
{LSNode* p;while (ps->next != NULL){p = ps->next;ps->next = p->next;free(p);}
}
栈的应用场景
1.表达式求值
在数学表达式求值中,栈发挥着关键作用。例如,对于后缀表达式(逆波兰表达式),我们可以利用栈来高效地计算结果。后缀表达式将运算符放在操作数之后,避免了括号带来的优先级判断复杂性。计算时,从左到右扫描后缀表达式,遇到操作数就将其入栈,遇到运算符则从栈中弹出相应数量的操作数进行运算,并将结果入栈。最终,栈顶元素即为表达式的计算结果。以表达式 “3 4 + 2 *” 为例,计算过程如下:
扫描到 3,入栈,栈:[3]
扫描到 4,入栈,栈:[3, 4]
扫描到 +,弹出 4 和 3,计算 3 + 4 = 7,将 7 入栈,栈:[7]
扫描到 2,入栈,栈:[7, 2]
扫描到 *,弹出 2 和 7,计算 7 * 2 = 14,将 14 入栈,栈:[14]
最终结果为 14
2.括号匹配
在编译器和文本编辑器中,常常需要检查代码中的括号是否正确匹配,如圆括号、方括号和花括号。利用栈可以轻松解决这个问题。当遇到左括号时,将其入栈;遇到右括号时,从栈中弹出对应的左括号进行匹配。如果在匹配过程中栈为空或者匹配失败,说明括号不匹配。例如,对于字符串 “{[()]}”,处理过程如下:
遇到 {,入栈,栈:[{]
遇到 [,入栈,栈:[{, []
遇到 (,入栈,栈:[{, [, (]
遇到 ),弹出 (进行匹配,栈:[{, []
遇到 ],弹出 [进行匹配,栈:[{]
遇到 },弹出 {进行匹配,栈:[]
匹配成功
3.函数调用栈
在程序执行过程中,函数调用是通过栈来管理的。当一个函数被调用时,它的相关信息,如参数、局部变量和返回地址等,会被压入栈中。当函数执行完毕返回时,这些信息会从栈中弹出,程序继续执行调用函数的下一条指令。例如,在一个包含多个函数嵌套调用的程序中,栈记录了函数调用的顺序和状态,确保函数能够正确返回和继续执行。假设函数 A 调用函数 B,函数 B 又调用函数 C,栈的状态变化如下:
调用 A,A 的相关信息入栈,栈:[A]
A 中调用 B,B 的相关信息入栈,栈:[A, B]
B 中调用 C,C 的相关信息入栈,栈:[A, B, C]
C 执行完毕返回,C 的信息出栈,栈:[A, B]
B 执行完毕返回,B 的信息出栈,栈:[A]
A 执行完毕返回,A 的信息出栈,栈:[]
4.深度优先搜索(DFS)
在图论和搜索算法中,深度优先搜索常常用栈来实现。在遍历图的过程中,从起始节点开始,将其入栈。然后,每次从栈中弹出一个节点,访问该节点,并将其未访问过的邻接节点入栈,直到栈为空。这样的方式使得搜索沿着一条路径尽可能深地探索下去,直到无法继续,然后回溯到上一个节点继续探索其他路径。
5.浏览器历史记录
我们日常使用的浏览器,其历史记录功能也运用了栈的思想。当我们依次访问网页 A、B、C 时,这些网页依次被压入栈中。当我们点击 “后退” 按钮时,就相当于执行出栈操作,从栈顶弹出当前页面,回到上一个页面。例如,访问顺序为 A -> B -> C,栈的状态为 [C, B, A],点击 “后退”,C 出栈,回到 B 页面,栈变为 [B, A]
总结
栈作为一种简单而强大的数据结构,以其独特的后进先出特性,在众多领域展现出高效的应用价值。无论是复杂的算法实现,还是日常使用的软件功能,栈都默默发挥着重要作用。通过对栈的概念、操作、实现方式以及应用场景的深入学习,我们不仅掌握了一种基础的数据结构,更能在编程实践中灵活运用它来解决各种实际问题。在未来的编程之旅中,希望你能充分利用栈的优势,优化代码,提升程序的性能和效率。让我们继续探索数据结构的奇妙世界,解锁更多编程的奥秘!
相关文章:
容器适配器-stack栈
C标准库不只是包含了顺序容器,还包含一些为满足特殊需求而设计的容器,它们提供简单的接口。 这些容器可被归类为容器适配器(container adapter),它们是改造别的标准顺序容器,使之满足特殊需求的新容器。 适配器:也称配置器,把一…...
7-6 混合类型数据格式化输入
本题要求编写程序,顺序读入浮点数1、整数、字符、浮点数2,再按照字符、整数、浮点数1、浮点数2的顺序输出。 输入格式: 输入在一行中顺序给出浮点数1、整数、字符、浮点数2,其间以1个空格分隔。 输出格式: 在一行中…...
【UE5 C++课程系列笔记】31——创建Json并保存为文件
目录 方式一(不推荐) 方式二(推荐) 一、生成普通Json对象 二、对象嵌套对象 三、对象嵌套数组 四、对象嵌套数组再嵌套对象 方式一(不推荐) 如下代码实现了把JSON字符串保存到文件中 #include &qu…...
Photoshop 2025 Mac中文 Ps图像编辑软件
Photoshop 2025 Mac中文 Ps图像编辑软件 文章目录 Photoshop 2025 Mac中文 Ps图像编辑软件一、介绍二、效果三、下载 一、介绍 Adobe Photoshop 2025 Mac版集成了多种强大的图像编辑、处理和创作功能。①强化了Adobe Sensei AI的应用,通过智能抠图、自动修复、图像…...
linux文件上传下载lrzsz
lrzsz 是一个在 Linux 系统中用于通过串行端口(如 ZMODEM、XMODEM、YMODEM 等协议)进行文件上传和下载的工具集。它通常用于在终端环境中通过串口或 SSH 连接传输文件。 安装 lrzsz 在大多数 Linux 发行版中,你可以使用包管理器来安装 lrzsz。 Debian/Ubuntu: sudo apt-ge…...
MySQL超全笔记
1、初识SQL 什么是数据库 数据库 ( DataBase , 简称DB ) 概念 : 长期存放在计算机内,有组织,可共享的大量数据的集合,是一个数据 “仓库” 作用 : 保存,并能安全管理数据(如:增删改查等),减少冗余… 数据库总览 : 关系型数据库 ( SQL ) MySQL , Oracle , SQL Server , SQ…...
使用Redis构架你自己的私有大模型
使用Redis构架你自己的私有大模型--楼兰 Redis你通常用来做什么?缓存?分布式锁?数据过滤器?不够不够,这远远不够。之前给大家分享过基于Redis Stack提供的一系列插件,完全可以把Redis作为一个类似于Elastic Search的JSON数据库使用。不光可以存储并操作JSON格式的数据…...
2.4路径问题专题:LeeCode 931.下降路径最小和
动态规划解决最小下降路径和问题 1. 题目链接 LeetCode 931. 最小下降路径和 2. 题目描述 给定一个 n x n 的整数矩阵 matrix,找到一条从第一行到最后一行的下降路径,使得路径上的数字和最小。下降路径可以从第一行的任意元素出发,每一步…...
从内核到应用层:Linux缓冲机制与语言缓冲区的协同解析
系列文章目录 文章目录 系列文章目录前言一、缓冲区1.1 示例11.2 缓冲区的概念 二、缓冲区刷新方案三、缓冲区的作用及存储 前言 上篇我们介绍了,文件的重定向操作以及文件描述符的概念,今天我们再来学习一个和文件相关的知识-----------用户缓冲区。 在…...
【AI News | 20250403】每日AI进展
AI Repos 1、llm-server-docs 项目提供了一份基于Debian系统的本地语言模型服务器搭建指南,适用于Linux初学者。教程涵盖驱动安装、GPU功耗设置、自动登录配置及开机自启脚本部署等关键步骤,支持Ollama/vLLM等多种OpenAI兼容方案。方案设计强调四大原则…...
深入理解SQL中的<>运算符:不等于的灵活运用
在SQL的世界里,数据的筛选与查询是最常见的操作之一。在编写查询语句时,比较运算符是我们不可忽视的工具,其中,<> 运算符作为 不等于 的代表,起着至关重要的作用。它不仅能够帮助我们筛选出符合特定条件的数据&a…...
单网卡上绑定多个虚拟IP(AI回答)
单网卡绑定多个虚拟IP的实现方法 一、Linux系统配置方案 1. 手动绑定少量IP地址(适用于CentOS/RHEL) 步骤1:进入网络配置目录 cd /etc/sysconfig/network-scripts/步骤2:复制并重命名网卡配置文件 cp ifcfg-eth0 i…...
数据清洗的具体内容
(一)ETL介绍 “ETL,是英文Extract-Transform-Load的缩写,用来描述将数据从来源端经过抽取(Extract)、转换(Transform)、加载(Load)至目的端的过程。ETL一词较…...
小家电等电子设备快充方案,XSP15支持全协议和支持MCU与电脑传输数据
随着USB-C的普及,市面上消费者PD充电器越来越多,如何让小家电等电子产品也能够支持PD协议快充呢?就需要加入一颗汇铭达XSP15取电协议芯片,这颗芯片不仅能支持取电,还能通过串口读取充电器支持的最大输出功率和支持外部…...
手动实现一个迷你Llama:手动实现Llama模型
进阶的 LLM Llama模型教学一、库导入二、实现 ModelArgs 参数类构建Transformer 模型参数解释 三、实现均方根归一化(RMSNorm,LayerNorm 的一种变体)层定义与原理RMSNorm 公式与 LayerNorm 的对比RMSNorm 的优点RMSNorm 的实现RMSNorm 的关键…...
缺页异常导致的iowait打印出相关文件的绝对路径
一、背景 在之前的博客 增加等IO状态的唤醒堆栈打印及缺页异常导致iowait分析-CSDN博客 里,我们进一步优化了D状态和等IO状态的事件的堆栈打印,补充了唤醒堆栈打印,也分析了一种比较典型的缺页异常filemap_fault导致的iowait的情况。 在这篇…...
记录学习的第十七天
今天对昨天下午的洛谷蓝桥杯模拟赛和今天早上的力扣周赛进行复盘。 昨天的蓝桥杯模拟赛,硬坐了4个小时,只会做前面的三道入门题。😥而且第一道填空题竟然还算错了。其他的五道题我都没啥思路了,实在难受啊! Q1:这道题硬…...
全面解析 Mybatis 与 Mybatis-Plus:深入原理、实践案例与高级特性对比
全面解析 Mybatis 与 Mybatis-Plus:深入原理、实践案例与高级特性对比 🚀 前言一、基础介绍 ✨1. Mybatis 简介 🔍2. Mybatis-Plus 简介 ⚡ 二、核心区别与高级特性对比 🔎1. 开发模式与配置管理2. 功能丰富度与扩展性3. 自动填充…...
Ubuntu 22.04 一键部署openManus
openManus 前言 OpenManus-RL,这是一个专注于基于强化学习(RL,例如 GRPO)的方法来优化大语言模型(LLM)智能体的开源项目,由来自UIUC 和 OpenManus 的研究人员合作开发。 前提要求 安装deepseek docker方式安装 ,windows 方式安装,Linux安装方式...
lib-zo,C语言另一个协程库,dns协程化, gethostbyname
lib-zo,C语言另一个协程库,dns协程化, gethostbyname 另一个 C 协程库 https://blog.csdn.net/eli960/article/details/146802313 本协程库 支持 DNS查询 协程化. 禁用所有 UDP 协程化 zvar_coroutine_disable_udp 1;禁用 53 端口的UDP 协程化 zvar_coroutine_disable_ud…...
强化学习_Paper_1988_Learning to predict by the methods of temporal differences
paper Link: sci-hub: Learning to predict by the methods of temporal differences 1. 摘要 论文介绍了时间差分方法(TD 方法),这是一种用于预测问题的增量学习方法。TD 方法通过比较连续时间步的预测值之间的差异来调整模型,…...
虚拟电商-话费充值业务(六)话费充值业务回调补偿
一、话费充值回调业务补偿 业务需求:供应商对接下单成功后充吧系统将订单状态更改为:等待确认中,此时等待供应商系统进行回调,当供应商系统回调时说明供应商充值成功,供应商回调充吧系统将充吧的订单改为充值成功&…...
Apache httpclient okhttp
学习链接 okhttp github okhttp官方使用文档 SpringBoot 整合okHttp okhttp3用法 Java中常用的HTTP客户端库:OkHttp和HttpClient(包含请求示例代码) 深入浅出 OkHttp 源码解析及应用实践 httpcomponents-client github apache httpclie…...
SQL Server 2022 读写分离问题整合
跟着热点整理一下遇到过的SQL Server的问题,这篇来聊聊读写分离遇到的和听说过的问题。 一、读写分离实现方法 1. 原生高可用方案 1.1 Always On 可用性组(推荐方案) 配置步骤: -- 1. 启用Always On功能 USE [master] GO ALT…...
Docker部署Blinko:打造你的个性化AI笔记助手与随时随地访问
文章目录 前言1. Docker Compose一键安装2. 简单使用演示3. 安装cpolar内网穿透4. 配置公网地址5. 配置固定公网地址 前言 嘿,小伙伴们,是不是觉得市面上那些单调乏味的笔记应用让人提不起劲?今天,我要给大家安利一个超炫酷的开源…...
Python Cookbook-5.2 不区分大小写对字符串列表排序
任务 你想对一个字符串列表排序,并忽略掉大小写信息。举个例子,你想要小写的a排在大写的 B 前面。默认的情况下,字符串比较是大小写敏感的(比如所有的大写字符排在小写字符之前)。 解决方案 采用 decorate-sort-undecorate(DSU)用法既快又…...
安全业务的manus时代即将到来
“(人)把业务流程任务化,把任务工具化,再把工具服务化,剩下的交给智能体。” 一、自动化与智能化浪潮下的安全业务变革 近期,笔者着迷于模型上下文协议(Model Context Protocol,简称MCP),这项技术所带来的变革性力量令人惊叹。在对多个技术案例进行实践的过程中,笔者…...
程序化广告行业(55/89):DMP与DSP对接及数据统计原理剖析
程序化广告行业(55/89):DMP与DSP对接及数据统计原理剖析 大家好呀!在数字化营销的大趋势下,程序化广告已经成为众多企业实现精准营销的关键手段。上一篇博客我们一起学习了程序化广告中的人群标签和Look Alike原理等知…...
【文献研究】铝对热冲压加热过程中锌氧化的影响
在热冲压过程中,镀锌铁板和镀锌板等镀锌钢板表面发生Zn氧化。为了阐明镀锌层中的Al对Zn氧化的影响,本研究研究了镀锌钢板上添加和不添加Al时形成的ZnO量。发现添加铝后ZnO量减少。对添加铝的镀锌钢板的显微组织分析表明,添加的Al在热冲压后Zn…...
Win11本地从零开始部署dify全流程
1.安装wsl和打开Hyper-V功能(前置准备) 这个是为了支持我们的Docker Desktop运行。 1.1.安装wsl 使用管理员身份运行命令行。 如果显示 “无法与服务器建立连接就执行“,表示没有安装wsl,如果更新成功,那就不用执行…...
