C++ stack容器

目录

一,stack的基本操作

二,题目练习

A---表达式括号匹配

B---括弧匹配检验

C---车厢调度

D---字符串匹配


一,stack的基本操作

#include<iostream>
#include<stack> //引用栈的文件

using namespace std;

int main()
{
	stack<int> s; //默认构造方法
	//stack<double> s;  也可以构造别的类型的栈
	//stack<string> s; 
	
	int num=1;
	s.push(num);//入栈,将num的值存入栈中
	
	cout<<"num="<<s.top()<<endl;//输出栈顶
	s.pop();//出栈
	
	if(s.empty()) cout<<"栈为空"<<endl; //判断栈是否为空 
	
	for(int i=0;i<5;i++) s.push(i); 
	cout<<"栈的大小="<<s.size()<<endl; //栈的大小 
	
	//拷贝调用函数的两种写法
	stack<int> s2=s; //这里也是拷贝调用 
	stack<int> s3(s);//都是将s里的内容拷贝给s2或s3
	
	//这种写法才是赋值 
	stack<int> s4;
	s4=s;
	return 0;
} 

二,题目练习

A---表达式括号匹配

题目描述

假设一个表达式有英文字母(小写)、运算符(+,—,*,/)和左右小(圆)括号构成,以“@”作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回"YES";否则返回"NO"。表达式长度小于255,左圆括号少于20个。

输入

输入表达式(只有1行,长度小于255)

输出

输出包括一行,即"YES"或"NO"

样例输入 Copy

【样例输入1】
2*(x+y)/(1-x)@
【样例输入2】 
(25+x)*(a*(a+b+b)@

样例输出 Copy

【样例输出1】
YES
【样例输出2】 
NO

AC代码

#include <iostream>
#include <stack>
#include <string>
 
using namespace std;
 
int main() {
     
    string expression;//字符串长度 
    stack<char> s;
     
    getline(cin, expression, '@'); // 以@作为结束符,读入表达式
    for (int i = 0; i < expression.length(); i++) {
        if (expression[i] == '(') {//左括号入栈 
            s.push(expression[i]);
        } 
        else if (expression[i] == ')') {
            if (s.empty() || s.top() != '(') {//读入右括号时,若栈为空或栈顶不是左括号,则输出NO,终止程序 
                cout << "NO" << endl;
                return 0;
            } else {
                s.pop();//若成功,则左括号出栈 
            }
        }
    }
    if (s.empty()) {//若栈为空,则输出YES 
        cout << "YES" << endl;
    } else {//不为空则代表左括号多了 
        cout << "NO" << endl;
    }
    return 0;
}

B---括弧匹配检验

题目描述

       假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,如([]())或[([][])]等为正确的匹配,[(])或([]()或(()))均为错误的匹配。

现在的问题是,要求检验一个给定表达式中的括弧是否正确匹配?

输入一个只包含圆括号和方括号的字符串,判断字符串中的括号是否匹配,匹配就输出 “OK” ,不匹配就输出“Wrong”。

输入一个字符串:[([][])],输出:OK

输入

       输入仅一行字符(字符个数小于255)

输出

匹配就输出 “OK” ,不匹配就输出“Wrong”。

样例输入 Copy

[(])

样例输出 Copy

Wrong

AC代码

#include<iostream>
#include<stack>
#include<string>//调用getlinewen()函数 
 
using namespace std;
 
int main()
{
    string s;
    stack<char> a;
    getline(cin,s,'\n');//输入字符串,遇到'\n'停止 
     
    for(int i=0;i<s.length();i++){
        if(s[i]=='('||s[i]=='['){//是括号的左边就进栈 
            a.push(s[i]);
        }
        else if(s[i]==')'){
            if(a.empty()||a.top()!='('){
                cout<<"Wrong"<<endl;
                return 0;
            }
            else{
                a.pop();
            }
        }
        else if(s[i]==']'){
            if(a.empty()||a.top()!='['){
                cout<<"Wrong"<<endl;
                return 0;
            }
            else{
                a.pop();
            }
        }
    }
     
    if(a.empty()){
        cout<<"OK"<<endl;
    }
    else{//不为空则代表左括号多了
        cout<<"Wrong"<<endl;
    }
    return 0;
}

C---车厢调度

题目描述

有一个火车站,铁路如图所示,每辆火车从A驶入,再从B方向驶出,同时它的车厢可以重新组合。假设从A方向驶来的火车有n节(n<=1000),分别按照顺序编号为1,2,3,…,n。假定在进入车站前,每节车厢之间都不是连着的,并且它们可以自行移动到B处的铁轨上。另外假定车站C可以停放任意多节车厢。但是一旦进入车站C,它就不能再回到A方向的铁轨上了,并且一旦当它进入B方向的铁轨,它就不能再回到车站C。

       负责车厢调度的工作人员需要知道能否使它以a1,a2,…,an的顺序从B方向驶出,请来判断能否得到指定的车厢顺序。

输入

输入文件的第一行为一个整数n,其中n<=1000,表示有n节车厢,第二行为n个数字,表示指定的车厢顺序。

输出

如果可以得到指定的车厢顺序,则输出一个字符串”YES”,否则输出”NO”(注意要大写,不包含引号)。

样例输入 Copy

5
5 4 3 2 1

样例输出 Copy

YES

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
 
int main(){
    stack <int> q;
    int a,b[1000+5],j=1;
    scanf("%d",&a);
    for(int i=1;i<=a;i++){
        scanf("%d",&b[i]);
    }
     
    for(int i=1;i<=a;i++){
        q.push(i);//依次进栈
        while(!q.empty()&&q.top()==b[j]){//直到栈顶与想要的值相同时出栈 
            j++;
            q.pop();
        }       
    }
    if(q.empty()==1){//若栈为空,则代表符合车厢顺序,输出“YES” 
        printf("YES");
    }
    else{
        printf("NO");
    }
    return 0;
}

D---字符串匹配

题目描述

字符串中只含有括号 (),[],<>,{},判断输入的字符串中括号是否匹配。如果括号有互相包含的形式,从内到外必须是<>,(),[],{},例如。输入: [()] 输出:YES,而输入([]), ([])都应该输出NO。

输入

       第一行为一个整数n,表示以下有多少个由括好组成的字符串。接下来的n行,每行都是一个由括号组成的长度不超过255的字符串

输出

 在输出中有N行,每行都是YES或NO。

样例输入 Copy

5
{}{}<><>()()[][]
{{}}{{}}<<>><<>>(())(())[[]][[]]
{{}}{{}}<<>><<>>(())(())[[]][[]]
{<>}{[]}<<<>><<>>>((<>))(())[[(<>)]][[]]
><}{{[]}<<<>><<>>>((<>))(())[[(<>)]][[]]

样例输出 Copy

YES
YES
YES
YES
NO

难点:符号优先级的考虑,可以用switch-case()来进行条件判断

AC代码

#include <iostream>
#include <stack>
#include <string>
using namespace std;

//检验符号优先级问题
int check(char c, stack<char> st) {
    if (st.empty()) return 1;
    else {
        switch (c) {
            //{入栈时,前面不能是  [ ( <   
        case '{': if (st.top() == '[' || st.top() == '(' || st.top() == '<') return 0;
            // [ 入栈时  前面不能是  ( < 
        case '[': if (st.top() == '(' || st.top() == '<') return 0;
            //  ( 入栈时  前面不能是 < 
        case '(': if (st.top() == '<') return 0;
            // < 可以直接入栈  
        case '<': st.push(c); break;
            //  () 差1  其他括号的差2     
        }
        return 1;
    }
}


// 函数用于判断括号是否匹配
bool isMatchingPair(char opening, char closing) {
    return (opening == '(' && closing == ')') ||
        (opening == '[' && closing == ']') ||
        (opening == '{' && closing == '}') ||
        (opening == '<' && closing == '>');
}

// 函数用于判断字符串中的括号是否平衡
bool isBalanced(string expr) {
    stack<char> st; // 用于存放左括号的栈
    for (char c : expr) {//将字符串expr中的每个字符赋值给c,遍历
        if (c == '(' || c == '[' || c == '{' || c == '<') {
            if (check(c,st)) st.push(c); // 遇到左括号,入栈
            else return false;
        }
        else if (c == ')' || c == ']' || c == '}' || c == '>') {
            if (st.empty() || !isMatchingPair(st.top(), c)) {
                return false; // 遇到右括号,检查栈顶是否与之匹配,不匹配则返回false
            }
            st.pop(); // 匹配,则弹出栈顶元素
        }
    }
    return st.empty(); // 若栈为空,则括号平衡,返回true;否则返回false
}

int main() {
    int n;
    cin >> n; // 输入测试数据组数
    cin.ignore(); // 忽略读取n后的换行符
    for (int i = 0; i < n; i++) {
        string expr;
        getline(cin, expr); // 读取每组测试数据的括号字符串
        if (isBalanced(expr)) {
            cout << "YES" << endl; // 判断括号是否平衡并输出结果
        }
        else {
            cout << "NO" << endl;
        }
    }
    return 0;
}

E---情书

雄雄学长的智商高达180,但他有个憨憨的习惯——写英语的时候喜欢把每一个单词都倒过来写。现在他写了一封给女神的情书,但是因为他的坏习惯,女神看不懂他的信,来找你帮忙。你能帮雄雄学长,向女神翻译他的信吗?

Input

输入包含多组数据。 第一行输入一个正整数 T 表示总的行数。接下来是T行。
每行包含一些单词,每行最多1000个字符。

Output

对于每一行输入的每个单词,请你都把他倒过来,雄雄学长会谢谢你的哟。
注意,雄雄学长只会将每个由空格所分隔的单词倒过来写,但单词间的顺序不会变。

Sample Input

3
!hO yM .raed
m'I .gnoixgnoix
I evol .uoy

Sample Output

Oh! My dear.

I'm xiongxiong.
I love you.

实现:以空格为标志,将输入的字符进栈,当入读空格时,出栈

AC代码

#include<iostream>
#include<string.h>
#include<sstream>
#include<stack>
#include<ctype.h>
using namespace std;

int main(){
    string s;
    while(getline(cin, s) && s != "0"){
        //判断是否为0
        stack<double> nums;
        stringstream s1(s);
        //用stringstream分割空格
        while(s1 >> s){
            if(isdigit(s[0])){
                //判断当前是否数字
                stringstream s2;
                double num;
                s2 << s;
                s2 >> num;
                nums.push(num);
                //存入数字
            }else{
                if(s == "+" || s == "-"){
                    if(s == "-"){
                        //如果是减,读入后面的数字*-1存进栈里
                        double num;
                        s1 >> num;
                        nums.push(num * -1);
                    }
                }else{
                    //如果是乘除,读入后面的数字运算后存进栈里
                    double num;
                    s1 >> num;
                    double num1 = nums.top();
                    nums.pop();
                    if(s == "*"){
                        nums.push(num1 * num);
                    }else{
                        nums.push(num1 / num);
                    }
                }
            }
        }   
        //栈内只剩下+,将所有的数字加起来
        double num = nums.top();
        nums.pop();
        while(nums.size()){
            double num1 = nums.top();
            nums.pop();
            num = num + num1;
        } 
        printf("%.2lf\n", num);
    }
    
    return 0;
}

E---计算器

读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。

Input

测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。

Output

对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。

Sample

InputcopyOutputcopy
1 + 2 
4 + 2 * 5 - 7 / 11 0 
3.00 
13.36 

难点:符号优先级的考虑,字符串的读取和转换类型。遇到乘除则读取后面的数字直接计算,遇到减,则之间将后面的数字变为负数。最后把所有的数加起来。关于字符串的处理可以使用stringstream。

AC代码

#include<iostream>
#include<string.h>
#include<sstream>
#include<stack>
#include<ctype.h>
using namespace std;

int main() {
    string s;
    while (getline(cin, s) && s != "0") {
        //判断是否为0
        stack<double> nums;
        stringstream s1(s);
        //用stringstream分割空格
        while (s1 >> s) {//从s1中逐步读取字符串,并赋值给s
            if (isdigit(s[0])) {
                //判断当前是否数字
                stringstream s2;
                double num;
                s2 << s; 
                s2 >> num;//将字符串s变为double类型
                nums.push(num);  //存入数字
            }
            else {
                if (s == "+" || s == "-") {
                    if (s == "-") {
                        //如果是减,读入后面的数字*-1存进栈里
                        double num;
                        s1 >> num;
                        nums.push(num * -1);
                    }
                }
                else {
                    //如果是乘除,读入后面的数字运算后存进栈里
                    double num;
                    s1 >> num;
                    double num1 = nums.top();
                    nums.pop();
                    if (s == "*") {
                        nums.push(num1 * num);
                    }
                    else {
                        nums.push(num1 / num);
                    }
                }
            }
        }
        //栈内只剩下+,将所有的数字加起来
        double num = nums.top();
        nums.pop();
        while (nums.size()) {
            double num1 = nums.top();
            nums.pop();
            num = num + num1;
        }
        printf("%.2lf\n", num);
    }

    return 0;
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值