栈是一种特殊的线性表,其插入操作和删除操作限定在表的一端进行,这一段被称为“栈顶”(top),相对的另一端称为“栈底”(bottom)。插入操作一般称之为“压栈”(push),删除操作称之为“退栈”(pop)。栈的特点是“先进后出” (LIFO,First In Last Out) 。
stack<typename> 栈的名字;
其中typename是想要的数据类型。
哦,对了,要使用栈,还需要加上一个头文件:(加了万能头文件就不需要了)
#include
如果要存int,可以这么写:
stack<int> s
假设已经定义一个栈,名字是s,那么就有这些函数:
s.push(x); //插入元素,x表示要插入的值,什么都行(但是类型必须和定义的相同)
s.pop(); //将栈顶弹出,无返回值
s.empty(); //判断是否是空栈
s.size(); //返回栈中有多少个元素
s.top(); //返回栈顶
s.swap(s2); //交换s和s2里面的值(s2需要和s是一个类型)
stack默认是空队列,如果不想怎么办?
假设已经定义了s1是stack<int>类型,那么可以这么写:
stack<int> s2(s1);
注意!stack没有重载=号!
#include
#include
using namespace std;
int main(int argc,char* argv[],char** env){
stack<int> s;
for(int i=1;i<=5;i++)
s.push(i);
while(!s.empty()){ //只要非空就循环
cout<<s.top()<<' ';
s.pop(); //这一步千万不要忘了
}
cout<<endl;
return 0;
}
分析:不是括号不需要入栈,如果是左括号就入栈,如果是右括号就看栈顶是不是左括号,如果是,就把左括号弹出,否则输出NO,结束程序。如果最后栈为空(所有左括号都被弹出了),输出YES,否则输出NO。
分析:其实和上一道差不多,只不过多了几组数据和优先级,可以一组数据一组数据的做,再弄一个栈,来保存每一个的最大的优先级是多少,在入栈的时候判断是否可行,如果可行把这个栈加上这个的优先级,在出栈的同时把这个栈也删一个。
分析:还是先分离,因为符号肯定比数字少一个,所以循环数字就行了,每循环一次就把这个数入栈,如果符号没越界,那么就判断符号是什么,如果是“+”,把栈顶的两个数入栈,否则把这两个数乘起来在对10000取模,再把结果入栈。因为栈里面的数都是要加的,所以把这些数加起来(加的同时要对10000取模),再输出
分析:可以遍历一遍,把数找出来入栈,如果是符号,从栈里弹出两个做运算(注意要下面的-上面的(下面的/上面的))
分析,用了这个方法:
中缀表达式值(expr)
--------------------------------------分割线--------------------------------------
分析:可以用dfs(会超时),把还没入栈的队和栈作为参数,可以有两种操作:1.把栈顶弹出(需要判断是否为空)2.把待入栈的队列里面的第一个入栈。
分析(一组数据):可以把输入的出栈序列的值改为在入栈序列中的位置,然后遍历b数组,如果已入栈, 则看栈顶是否是它,如果不是,可以直接输出“No”,看下一组数据了。如果未入栈,那就把它前面的都入栈,最后输出“Yes”。
分析:我这里用一个计数器来记录出栈了几个,如果都出栈了,就结束循环
自己尝试做一做吧~
#include
#include
#include
using namespace std;
int main(int argc,char* argv[],char** env){
char c;
stack<char> s;
do{
cin>>c;
if(c=='(')
s.push(c); //压栈
else if(c==')'){
if(!s.empty()&&s.top()=='(')
s.pop(); //把左括号弹出
else{
cout<<"NO\n"; //没有左括号
return 0;
}
}
}while(c!='@');
if(s.empty()) //如果左括号都弹出了
cout<<"YES\n";
else
cout<<"NO\n";
return 0;
}
#include
#include
#include
#include
#include
using namespace std;
int priority(char c) { //返回c的优先级
if(c=='<'||c=='>')
return 1;
if(c=='('||c==')')
return 2;
if(c=='['||c==']')
return 3;
if(c=='{'||c=='}')
return 4;
return -1;
}
bool is_left(char c) { //判断是否是左括号
return c=='('||c=='['||c=='{'||c=='<';
}
bool is_right(char c) {
return c==')'||c==']'||c=='}'||c=='>';
}
//两个括号是否匹配
bool match(char a,char b) {
if(!is_left(a)) //如果左边的不是左括号
return false;
if(a=='(')
return b==')';
if(a=='[')
return b==']';
if(a=='{')
return b=='}';
if(a=='<')
return b=='>';
}
//一个一个判断
bool func(stack<char>& s,char c,stack<int>& prioritys) {
if(is_left(c)) { //如果是左括号
if(prioritys.top()>=priority(c)) {
s.push(c);
prioritys.push(priority(c));
} else {
return false; //优先级太高
}
} else if(is_right(c)) { //如果是右边
if(!s.empty()&&match(s.top(),c)) { //如果匹配
s.pop();
if(!prioritys.empty()) //非空
prioritys.pop();
} else
return false;
}
return true;
}
bool check(string str) {
stack<char> s;
stack<int> prioritys; //优先级
prioritys.push(0x7fffffff); //很大很大的数
for(int i=0; i<str.size(); i++) {
char c=str[i];
if(!func(s,c,prioritys)) {
return false;
}
}
return s.empty();
}
int main(int argc,char* argv[],char** env) {
int n;
cin>>n;
getchar(); //以防把n后面的换行当成第一个字符
while(n--) {
string str;
getline(cin,str); //保险,其实完全可以用cin>>str;
if(check(str))
cout<<"YES\n";
else
cout<<"NO\n";
}
return 0;
}
#include
#include
#include
using namespace std;
bool is_digit(char c) {
return c>='0'&&c<='9';
}
string num[100003],operators; //数字和运算符
int calc(string str) { //分离
int n=0,len=str.size();
for(int i=0; i<len; ++i) {
if(is_digit(str[i])) {
num[n]+=str[i];
} else {
n++;
operators+=str[i];
}
}
return ++n; //因为什么,所以要加1?
}
int main(int argc,char* argv[],char** env) {
string str;
getline(cin,str);
int n=calc(str);
stack<int> s;
stack<char> op;
for(int i=0; i<n; i++) {
bool flag=false;
//下面用C++11的函数来把num[i]转换成int,用的要在Dev-C++
//编译选项->代码生成/优化->代码生成->语言标准 设置位ISO C++11或GNU C++11
int x=stoi(num[i]);
s.push(x%10000);
char c;
if(i+1<n)
c=operators.at(i); //或operators[i]
else
flag=true; //最后一个
if(op.empty()||op.top()=='+') {
op.push(c);
} else { //op.top=='*'
s.pop();
int y=s.top();
s.pop();
s.push(x*y%10000);
op.push(c); //别忘了把当前的加进去
}
if(flag) { //最后一个要在这里判断,为什么自己想想
int sum=0;
while(!s.empty()) {
sum+=s.top()%10000; //其实对不对10000取模都一样,因为反正push的时候
//都对10000取模了
sum%=10000; //这里非常重要,我就是没写这个才过不去,如果不写这个的话下面的
//cout<
s.pop();
}
cout<<sum<<endl;
return 0; //加不加随便,反正都是最后一轮
}
}
return 0;
}
#include
#include
#include
#include
using namespace std;
bool is_digit(char c) { //判断是否为数字,也可以用algorithm中的
return c>='0'&&c<='9';
}
int calc(string input) {
int x=0;
stack<int> s;
for(int i=0; i<input.size(); i++) {
char c=input[i];
if(is_digit(c)) { //如果是数字
x=x*10+c-'0'; //当前的数
} else {
if(c=='@') //结束符
break;
if(c=='.') //分隔符
s.push(x);
x=0; //清0
if(c=='+'||c=='-'||c=='*'||c=='/') { //是运算符
int b=s.top(); //注意要先取b,因为下面要a+b或a-b或a*b或a/b
s.pop(); //取一个弹出一个
int a=s.top();
s.pop(); //这一步很重要
switch(c) {
case '+': {
s.push(a+b);
break;
}
case '-': {
s.push(a-b);
break;
}
case '*': {
s.push(a*b);
break;
}
case '/': {
s.push(a/b);
break;
}
default: {
break;
}
}
}
}
}
return s.top(); //栈里面应该只剩结果了
}
int main(int argc,char* argv[],char** env) {
string s;
getline(cin,s); //保险
cout<<calc(s)<<endl;
return 0;
}
#include
#include
#include
using namespace std;
bool is_digit(char c) {
return c>='0'&&c<='9';
}
int priority(char c) { //优先级
if(c=='+'||c=='-')
return 1;
if(c=='*'||c=='/')
return 2;
}
string change(string str){ //把中缀表达式转成后缀表达式
string ans,x;
stack<char> s;
for(int i=0; i<str.size(); i++) {
char c=str[i];
if(is_digit(c)) {
x+=c;
if(i+1==str.size()||!is_digit(str[i+1])){
ans+=x; //将结果加这个数
ans+=' '; //为了区分是哪个数
x=""; //清空数
}
} else if(c=='+'||c=='-'||c=='*'||c=='/') {
while(1) {
if(s.empty()||s.top()=='(') {
s.push(c);
break;
} else if(priority(c)>priority(s.top())) {
s.push(c);
break;
} else {
char t=s.top();
s.pop();
ans+=t;
}
}
} else {
if(c=='(') {
s.push(c);
} else { //右括号
while(s.top()!='(') {
char t=s.top();
s.pop();
ans+=t;
}
s.pop(); //将左括号弹出,不要忘了
}
}
}
while(!s.empty()){
ans+=s.top();
s.pop();
}
return ans;
}
int main(int argc,char* argv[],char** env) {
string str;
getline(cin,str); //保险
cout<<change(str)<<endl;
return 0;
}
#include
#include
#include
#include
#include
using namespace std;
int n;
int out[1001]; //已出栈的
unsigned long long cnt=0;
void print(){
//测试
//for(int i=0;i
// cout<
//cout<
cnt++;
}
void dfs(int step,stack<int> s,int k,queue<int> q){ //k:out数组中的个数-1
if(s.empty()&&q.empty()){ //找到一种解
print();
return ;
}
if(!s.empty()&&s.top()==n){ //优化(其实也没多少)
for(int i=k;i<n;i++){
out[i]=s.top();
s.pop();
}
print();
return ;
}
if(s.empty()){ //如果栈为空,取下一个入栈
s.push(q.front());
q.pop();
dfs(step+1,s,k,q);
} else {
int t=s.top();
s.pop();
out[k]=t;
dfs(step+1,s,k+1,q);
s.push(t); //把t放回去
if(!q.empty()){
s.push(q.front());
q.pop();
dfs(step+1,s,k,q);
}
}
}
int main(int argc,char* argv[],char** env){
queue<int> q; //q:待入站的队列
stack<int> s;
cin>>n;
for(int i=2;i<=n;i++) //1已经入栈
q.push(i);
s.push(1); //把1入栈,因为完全可以把1入栈后出栈,所以不用担心别的数打头的输出不出来
dfs(1,s,0,q);
cout<<cnt<<endl; //记得输出
return 0;
}
#include
#include
#include
using namespace std;
bool check(int a[],int b[],bool is_pushed[],int n) {
stack<int> s;
for(int i=1; i<=n; i++) { //遍历b数组
if(is_pushed[b[i]]) { //b[i]已入栈
if(!s.empty()&&s.top()!=a[b[i]])
return false;
s.pop(); //如果等于,将这个数弹出
} else { //b[i]未入栈
//把a[b[i]]的前面的元素入栈.
int j=b[i],k;
is_pushed[j]=true;
for(k=j-1;k>0;k--) //找到没入栈的开头-1
if(is_pushed[k])
break;
for(int l=k+1; l<j; l++) { //把前面的都入栈
s.push(a[l]);
is_pushed[l]=true;
}
}
}
return true;
}
int main(int argc,char* argv[],char** env) {
int n,t;
cin>>t;
while(t--) {
map<int,int> mp; //mp[i]表示i在a数组中的下标
cin>>n;
int a[n+2],b[n+2],x; //a数组记录入栈序列,b数组存出栈序列的数在a[]中的下标
bool is_pushed[n+2]; //is_pushed[i]记录a[i]有没有入栈
for(int i=1; i<=n; i++) {
cin>>a[i];
//初始化
is_pushed[i]=0;
mp[a[i]]=i;
}
for(int i=1; i<=n; i++){
cin>>x;
b[i]=mp[x];
}
if(check(a,b,is_pushed,n)) //这里传is_pushed因为完全可以在输入的时候初始化,不需要在里面初始化
cout<<"Yes\n";
else
cout<<"No\n";
}
return 0;
}
#include
#include
#include
using namespace std;
int main(int argc,char* argv[],char** env){
stack<int> s; //栈里存在a数组中的下标
int x,n,c,cnt=0;
cin>>n>>c;
int a[n+2],begin=0,end=c-1; //窗口的开头和结尾
for(int i=0;i<n;i++)
cin>>a[i];
while(cnt<n){
//找a数组中最小
int MinIndex=min(begin,n-1);
for(int i=min(begin,n-1);i<=end&&i<n;i++){
if(a[i]<a[MinIndex])
MinIndex=i;
}
//判断
if(!s.empty()){ //栈非空
if(a[s.top()]<a[MinIndex]){ //如果栈顶元素比这个数还小
cout<<a[s.top()]<<' '; //出栈
cnt++;
a[s.top()]=0x7fffffff; //记录已经出栈了
end++;
s.pop();
} else {
//把前面的都入栈
for(int i=begin;i<MinIndex;i++){
if(a[i]<0x7fffffff){
s.push(i);
begin=i;
}
}
if(begin==MinIndex)
begin++;
else
begin+=2;
cout<<a[MinIndex]<<' '; //输出
cnt++;
a[MinIndex]=0x7fffffff;
end++;
}
} else { //栈为空
//把前面的都入栈
for(int i=begin;i<MinIndex;i++){
if(a[i]<0x7fffffff){
s.push(i);
begin=i;
}
}
if(begin==MinIndex)
begin++;
else
begin+=2;
cout<<a[MinIndex]<<' '; //也是输出
cnt++;
a[MinIndex]=0x7fffffff;
end++;
}
}
return 0;
}
栈的应用还有很多,先不说了,拜拜~