前言
栈的特点是“先进后出”;栈需要空间存储,如果站的深度太大,或者存进栈的数组太大,哪呢就会超出系统分配给栈的空间,导致栈溢出。
n个元素进栈,有C(2n,n)/(n+1) (C(2n,n)表示2n里取n)个出栈顺序(称为卡特兰数)
代码
long long res[67][67]={0};
long long C(long long n,long long m){
if(m==0 || m==n) return 1;
if(res[n][m] != 0)return res[n][m];
return res[n][m] = C(n-1,m)+ C(n-1,m-1);
}
int fun(int n)
{
long long sum = C(2*n,n);
return sum/(n+1);
}
一:STL stack
1.STL stack的有关操作
(1)stack<Type>s 定义栈的数据类型
(2)s.push(item) 将元素item放到栈顶
(3)s.top() 返回栈顶元素,且不会删除
(4)s.pop() 删除栈顶的元素,且不会返回,出栈时先使用top()获得栈顶元素,再用pop()删除栈顶元素
(5)s.size() 返回栈的元素个数
(6)s.empty() 判断栈是否为空,为空就返回true,否则返回false
2.题目:翻转字符串
输入样例:olleh 输出样例:hello
代码:
//方法1--利用栈
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
string str; //定义字符串
stack<char>s; //定义栈
int main()
{
getline(cin,str); //输入字符串--可以带空格
for(int i = 0;i < str.size();i++)
{
s.push(str[i]); //进栈
}
while(!s.empty()) //实现逆序输出
{
cout<<s.top(); //一个一个输出栈顶元素
s.pop();
}
return 0;
}
//方法2--利用字符串直接逆序输出
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
string s;
int main()
{
cin>>s; //从头输到尾 逆序时从尾到头输出
for(int i = s.size()-1;i >= 0;i--) //计算字符串的大小
{
cout<<s[i]; //直接输出
}
return 0;
}
二:手写栈
1.手写栈的相关操作
struct mystack{
char a[10010];
int t = 0;
void push(char x){ //存放栈元素
a[++t] = x;
}
char top(){
return a[t]; //返回栈顶元素
}
char pop(){ //弹出栈顶
t--;
}
int empty(){ //判断栈是否为空,为空返回1
return t==0?1:0;
}
}st;
三:单调栈
1.定义
单调栈是栈的一种适用形式,单调栈内的元素是单调递增或者单调递减的,有单调递增栈与单调递减栈,单调递减栈从栈顶到栈底是从小到大的顺序。
2.题目:单调栈
题目一:https://www.luogu.com.cn/problem/P5788
代码:
//输入输出用scanf 与 printf,用cin cout会TLE
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N = 3000000+10;
int n;
int a[N];
int rel[N];
stack<int>st;
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
scanf("%d",&a[i]);
}
for(int i = n;i >= 1;i--)
{
while(!st.empty()&&a[st.top()]<=a[i]) //栈顶元素没有i高,就弹出它,知道栈顶奶牛更高
{
st.pop();
}
if(st.empty()) //栈空,没有比他高的
rel[i] = 0;
else
rel[i] = st.top(); //输出栈顶
st.push(i);
}
for(int i = 1;i <= n;i++)
{
printf("%d ",rel[i]);
}
return 0;
}
题目二:https://www.luogu.com.cn/problem/P2947
代码:
//其实相当于上面题的另一种解法
#include<iostream>
using namespace std;
int n;
int t;
int a[100010], ans[100010];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=n-1;i>=1;i--)
{
t=i+1;
while(a[i]>=a[t] && a[t]>0)
t=ans[t];
ans[i]=t;
}
for(int i=1;i<=n;i++)cout<<ans[i]<<endl;
return 0;
}
四:相关题目
题目一:https://www.luogu.com.cn/problem/P1449
代码:
#include <bits/stdc++.h>
using namespace std;
stack<int>st;
int main()
{
long long t = 0,now = 0;
char ch;
int x,y,s = 0;
while((ch=getchar())!='@')
{
if(ch=='+')
{
x = st.top();
st.pop();
y = st.top();
st.pop();
st.push(x+y);
}
else if(ch=='-')
{
x = st.top();
st.pop();
y = st.top();
st.pop();
st.push(y-x);
}
else if(ch=='*')
{
x = st.top();
st.pop();
y = st.top();
st.pop();
st.push(x*y);
}
else if(ch=='/')
{
x = st.top();
st.pop();
y = st.top();
st.pop();
st.push(y/x);
}
else if(ch>='0'&&ch<='9')
{
s*=10;
s+=ch-'0';
}
else
{
st.push(s);
s = 0;
}
}
cout<<st.top()<<endl;
return 0;
}
题目二:https://www.luogu.com.cn/problem/P1739
代码:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
string s;
int main()
{
cin>>s;
int left = 0;
int flag = 0;
for(int i = 0;i < s.size();i++)
{
if(s[i]=='(')
left++;
if(s[i]==')')
left--;
if(left<0)
{
flag = 1;
}
}
if(left==0&&flag ==0)
cout<<"YES";
else
cout<<"NO";
}
题目三:https://www.luogu.com.cn/problem/P1981
代码:
#include <bits/stdc++.h>
using namespace std;
const int mod = 10000;
int x,s,t;
char c;
int main()
{
cin>>t;
while(scanf("%c",&c)&&c!='\n')
{
cin>>x;
if(c=='*')
{
t = x * t % mod;
}
else
{
s = (s+t)%mod;
t = x;
}
}
cout<<(s+t)%mod<<endl;
return 0;
}