# :-: **栈(Stack)**
* 本篇只是强调如何使用栈,请自行选择是否观看。
<br>
## **栈是什么**
* **栈**是一种非常重要的线性结构,从数据结构角度来看,栈也是线性表,其特殊性在于它是受限的线性表。
* **栈**的特性:后进先出(Last In First Out)
* 对于栈来说,表尾端有其特殊含义,成为**栈顶**(top),相应的,表头端称为**栈底**(bttom)。
* 不含元素的栈称为空栈。
<br>
## **栈的定义及操作**
* 假设栈 S 中的元素按照![](https://box.kancloud.cn/5c99734e47fb8ca68028b5b619b01042_208x21.png)的次序进栈,则称![](https://box.kancloud.cn/1b96178d6c3b10db12765a35ff101360_39x30.png)为栈底元素,![](https://box.kancloud.cn/39b0a5518181f5911501aef87f202f3e_41x32.png)为栈顶元素。出栈的第一个元素应该是栈顶元素(如下图所示)
* ![](https://box.kancloud.cn/c32518a86462934cdb942bc6dde1b50b_430x310.png)
* 举个例子:你在洗碗把洗好的碗编号为1、2、、、n依次摞起来,1号在最下面,向上编号依次增加,然后再从上到下把碗放好,这样的话,先被洗的碗,就后被放好。
#### **栈的操作**
* 定义栈
`stack<int> s; // 声明存储int类型数据的栈`
* 常用操作
`s.empty()//如果栈为空返回true,否则返回false
`
`s.size()//返回栈中元素的个数
`
`s.pop()//删除栈顶元素但不返回其值
`
`s.top()//返回栈顶的元素,但不删除该元素
`
`s.push(X)//在栈顶压入新元素 ,参数X为要压入的元素`
## **一些实例**
* [HDU2031进制转换](http://acm.hdu.edu.cn/showproblem.php?pid=2031),我们用栈来实现一下进制转换问题
```
#include <cstdio>
#include <stack>
using namespace std;
int main()
{
int N,R;
int negetive;//控制是否输出负号
while(~scanf("%d %d",&N,&R))
{
stack<int> s;//定义一个栈
negetive = 0;
if(N<0)
{
negetive = 1;
N = -N;
}
while(N)//利用栈来实现进制转换是非常方便的
{
s.push(N%R);//每次往栈里放入余数
N /= R;
}
if(negetive) printf("-");
while(s.size())//判断栈是否为空,我喜欢这样子用
{
int z = s.top();//取栈顶元素
if(z<10) printf("%d",z);
else printf("%c",z - 10 + 'A');
s.pop();//让栈顶元素出栈
}
puts("");//输出回车的另外一种方式
}
return 0;
}
```
* 栈在很多方面都具有很大的用处的,比如火车调度问题,括号匹配问题,表达式求值问题,都可以用栈来实现,
## **一些例题**
* [火车调度问题](http://acm.hdu.edu.cn/showproblem.php?pid=1022&tdsourcetag=s_pctim_aiomsg),问以前者进栈,正否以后者出栈
* [大鱼吃小鱼](http://www.51nod.com/Challenge/Problem.html#!#problemId=1289%3Ftdsourcetag=s_pctim_aiomsg)
* [Seinfeld](http://acm.hdu.edu.cn/showproblem.php?pid=3351&tdsourcetag=s_pctim_aiomsg)
* [括号配对问题](http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=2)
* [括号匹配(二)](http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=15)
* [表达式求值](http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=35)
建议把上边的问题给做一下
- 简介
- 零基础快速入门ACM
- C语言快速入门
- C语言快速入门
- C/C++基础
- 输入输出
- 数组和字符串
- 数组
- 字符数组
- 函数和递归
- C++标准容器库(STL)
- Vector
- Map
- Set
- String
- Stack
- Queue
- Priority_queue
- 贪心
- 硬币问题
- 区间调度问题
- 字典序最小问题
- 独木舟问题
- 搜索
- DFS
- BFS
- 剪枝
- 记忆化搜索
- 常用技巧
- 倍增
- 高精度
- 大数加法
- 大数减法
- 大数乘法
- 大数除法
- 大数阶乘
- 输入挂
- 前缀和
- 二分
- 本地预处理
- 尺取
- 枚举
- 坐标离散化
- 分治
- 数列分治
- 树上分治
- 平面分治
- 计算几何
- 凸包
- 点积
- 叉积
- 线段关系
- 皮克定理
- 最近点对
- 数据结构
- 线段树
- 树状数组
- 并查集
- 动态规划
- 基础知识
- 信息学竞赛中的动态规划
- 动态规划初步
- 最长上升子序列(LIS)
- 最长公共子序列(LCS)
- 最大子段和
- 背包问题
- 部分背包
- 0 1 背包
- 完全背包
- 多重背包
- 背包的可行性问题
- 线性DP
- 树形DP
- 区间DP
- 数位DP
- 动态规划优化
- 字符串
- KMP算法
- 拓展KMP
- 字符串Hash
- Manacher算法
- 后缀数组
- Trie树
- 博弈论
- Nim博弈
- Bash博弈
- 斐波那契博弈
- 威佐夫博弈
- SG函数
- 数论
- 整数研究
- 素数判断
- 素数筛选
- 快速幂
- 算数基本定理
- 最大公约数(Gcd)
- 费马小定理
- 扩展欧几里得
- 逆元
- 同余定理
- 组合数学
- 容斥原理
- 抽屉原理
- 卢卡斯(Lucas)
- 卡特兰(Catalan)
- 著名函数
- 欧拉函数
- 莫比乌斯函数
- 线性代数
- 矩阵运算
- 矩阵快速幂
- 图论
- 存图方法
- 邻接矩阵
- 邻接表
- Vector存图
- 链式前向星
- 图的遍历
- 拓扑排序
- 最短路
- Dijkstra算法
- SPFA算法
- Floyed 算法
- 最小生成树
- Prim算法
- Kruskal算法
- 最近公共祖先 (LCA)
- 二分图匹配
- 网络流
- 其他
- 莫队