今天来讲讲栈
栈是什么?
老样子,先来看一道题:
【栈】栈的基本操作
描述
栈的定义:栈是一种特殊的表这种表只在表头进行插入和删除操作。因此,表头对于栈来说具有特殊的意义,称为栈顶。相应地,表尾称为栈底。不含任何元素的栈称为空栈。
栈的逻辑结构:假设一个栈 SS 中从顶到底的元素为 a_n,a_{n-1},\ldots,a_1an,an−1,…,a1,则称 a_1a1 为栈底元素,a_nan 为栈顶元 素。栈中的元素按 a_1,a_2,..,a_{n-1},a_na1,a2,..,an−1,an 的次序进栈。在任何时候,出栈的元素都是栈顶元素。换句话说,栈的修改是按后进先出的原则进行的。因此,栈又称为后进先出 (Last In First Out) 表,简称为 LIFO 表。所以,只要问题满足 LIFO 原则,就可以使用栈。
举个生活中的例子,比如洗碗,先洗的碗在底层,后面洗的碗会叠在先洗的碗的上面。这样在使用的时候,最后洗的碗就会先拿。
在程序实现上,栈也是用数组来存放的,需要一个数组下标变量来控制数据在数组的存入和读取等操作。
由于 C++ 的 STL 本身提供了栈这种数据结构,你只要学会使用 STL 的栈操作就行了。
后面学的递归(回溯)算法,递归会调用系统栈是来实现(这个是递归内部实现,我们不用去操作),只是理解栈这个结构会帮助我们更好地理解递归这个算法。当然,栈本身在一些题目上也会用到。
首先看一下 C++ 栈的方法的基本用法:
push()
:向栈内压入一个成员;
pop()
:从栈顶弹出一个成员;
empty()
:如果栈为空返回true
,否则返回false
;
top()
:返回栈顶,但不删除成员;
size()
:返回栈内元素的大小;普通栈的操作:
#include<iostream> #include<stack> //使用栈需要的头文件 using namespace std; int x; int main(){stack <int>stk; //定义一个整数类型的栈变量 //入栈for(int i=0;i<50;i++){cin>>x;stk.push(x); // 数据入栈 }cout<<"栈的大小:"<<stk.size()<<endl;while(!stk.empty()){cout<<stk.top()<<endl; //取出栈顶数据 stk.pop(); //删除栈顶数据,就是出栈 }cout<<"栈的大小:"<<stk.size()<<endl;return 0; }
结构体栈的使用:
#include<iostream> #include<stack> //使用栈需要的头文件 using namespace std; struct people{int sg,tz;char xb; }; people x; int n; int main(){stack <people> stk; //定义一个结构体类型的栈变量 //入栈cin>>n;for(int i=0;i<n;i++){cin>>x.sg>>x.tz>>x.xb; stk.push(x); // 结构体数据入栈 }cout<<"栈的大小:"<<stk.size()<<endl;while(!stk.empty()){x= stk.top(); //取出栈顶数据cout<<x.sg<<" "<<x.tz<<" "<<x.xb<<endl; //取出栈顶数据 stk.pop(); //删除栈顶数据,就是出栈 }cout<<"栈的大小:"<<stk.size()<<endl;return 0; }
现给定一组栈的操作(入栈与出栈),要求按顺序输出出栈的数,和最终留在栈里的数。
输入
一行若干个正整数,以0
结尾。
操作有如下几种:
- 1 x:表示将 x 入栈;
- 2:表示将栈顶弹出。
输出
第一行按顺序输出出栈的数;无则输出空行;
如果出现栈满并且还有数据进栈则单行输出:the stack is full!
如果出现栈空并且还有数据出栈则单行输出:the stack is empty!
最后一行如果栈里还有数据则输出栈里的数(注意:出现栈满情况时也要输出栈里剩余的数)。
输入样例 1
1 3 1 2 2 1 1 2 0
输出样例 1
2 1 3
输入样例 2
1 3 2 2 1 3 1 4 1 5 1 6 0
输出样例 2
3the stack is empty!
提示
对于 100% 的数据,栈的最大容量为 300,每次需要入栈的正整数小于等于 10^9。
来源
lzy
首先我来讲一下展示怎么样的东西
这里有一个羽毛球筒
| |
| |
| |
| |
—
现在我把一号球放进去:
| |
| |
| |
|1|
—
现在我把二号球放进去:
| |
| |
|2|
|1|
—
现在我们要取出一个球,我们只能先取出2,再取出1(先进入的数字反而最后出来,也就是先进后出)(考试经常考哦)
| | ——>2(取出)
| |
| |
|1|
—
| | ——>2(取出)
| | ——>1(取出)
| |
| |
—
这就是栈,像一个羽毛球筒
栈怎么写?
定义是这样的:
stack<int> q;
//其中,<>里的数据类型代表q的类型
//比如现在q为int型
//如果把int改为longlong,q就是longlong型
其他的操作室这样的:
q.size()//求q的大小(元素个数,比如栈里有1和2,元素个数就是2)
!q.empty()//判断q是否为空(空就是没有元素)如果空了就返回1(真),否则返回2(假)
q.top();//获取栈顶的数字,比如刚刚的羽毛球筒,放了1和2,用这个就会返回2
q.pop();//弹出栈顶(把栈顶删掉),将最后一个放入的2拿出,就可以用这个
q.push(x);//入栈,也就是把x跟球一样放进栈里
//注意了!不管你怎么用,都要加个括号
//q.size()这种返回数字的东西,是可以当数字来用的
//比如if(q.size()==300) ,就是判断q的元素个数是不是等于300
//a=q.top();就是a=栈顶的那个数字
所以我们就可以解出最开始的那道题了:
#include<bits/stdc++.h>
using namespace std;
int main(){stack<int> q;//定义 long long a,x;//定义(a读的是前面的1或2) do{cin>>a;//读入 if(a==1){//a==1说明要入栈 if(q.size()==300){//如果说栈已经满了 cout<<endl<<"the stack is full!"<<endl;//输出 while(!q.empty()){//循环,栈没空就一直循环 cout<<q.top()<<" ";//输出栈顶 q.pop();//弹出栈顶,为下一次的输出做准备 } return 0;}//否则就可以正常入栈了 cin>>x;//读入 q.push(x);//入栈 }else if(a==2){//如果要弹出 if(q.empty()){//如果栈空了,就弹不了了 cout<<endl<<"the stack is empty!";//输出 return 0;}cout<<q.top()<<" ";//否则输出栈顶 q.pop();//弹出栈顶 }}while(a!=0);//a==0就是要停止输入了 cout<<endl;while(q.size()!=0){//循环,只要栈的元素个数!=0就一直循环 cout<<q.top()<<" ";//输出 q.pop();//弹出 }return 0;
}
你知道我写了多久吗?写了20分钟。这还不值得你给我点个赞吗?