栈的应用

为了使用栈,得加上:

#include<stack>
using namespace std

题目一(典型题目)

括号匹配问题
输出原理字符串,并在下面标出不能匹配的括号。不能匹配的左括号用‘$’标记,不能匹配的右括号用’?’标记
我们按照从左至右的顺序遍历字符串,将遇到的左括号都放入堆栈中等待匹配;若在遍历过程中遇到一个右括号:若堆栈非空,则栈顶左括号与之匹配;相反,若堆栈为空,则匹配失败
代码:

#include<stdio.h>
#include<stack>
using namespace std;
stack<int> S;
char str[110];
char ans[110];
int main()
{
    while(scanf("%s",str)!=EOF)
    {
        int i;
        //遍历字符串
        for(i=0;str[i]!=0,i++)
        {
          if(str[i]=='(')
          {
            S.push(i);
            ans[i]=' '; //暂定
          }
          else if(str[i]==')')
          {
            if(!S.empty())
            {
                ans[i]=' ';
                S.pop();
            }
            else
            {
                ans[i]='?';
            }
          }
          else
          {
           ans[i]=' ';
          }
        }
        //栈中是否有剩余左括号
        while(!S.empty())
        {
            ans[S.top()]='$';
            S.pop();
        }
        //为了使输出的为字符串
        ans[i] = 0;
        puts(str);
        puts(ans);
    }
    return 0;
}

题目二(典型)
表达式求值
读入一个只包含+ - * / 的非负整数计算表达式,计算该表达式的值
解题思路:

  1. 设立两个堆栈,一个用来保存运算符,一个用来保存数字
  2. 在表达式首尾添加标记运算符,该运算符运算优先级最低
  3. 从左到右依次遍历字符串,若遍历到运算符,则将其与运算符栈的站定元素进行比较: ①如果栈顶运算符的优先级或此时运算符栈为空,则将运算符压入栈中;②运算符栈顶元素大,则弹出栈顶元素,再从数字栈中依次弹出两个栈顶数字。完成相应运算后,将结果压入数字栈。③重复比较此时栈顶运算符与当前遍历到的运算符优先级。
  4. 若遍历到表达式中的数字,则直接压入数字栈
  5. 若运算符中金存有两个运算符且栈顶元素为我们认为添加的标记运算符,那么表达式运算结束。数字栈中唯一数字即为表达式的值

知识点:只有那个紧挨数组名的括号代表该数组的大小,后面那些括号代表的是这个数组的元素。 元素的大小必须是确定的,所以后面那些括号中的数字才不能省略!

while(gets(str))  //输入字符串,当其位于文件尾时,gets返回0

if(str[0]=='0' && str[1]==0) break; //输入字符串中只包含一个0

 while(!op.empty()) op.pop();
 while(!in.empty()) in.pop(); //清空数字栈和运算符栈,对于每个测试案例

函数中的参数什么时候需要加引用呢?如果要操作的数是你传入的数据,这时候就要加引用,例如交换两个数

完整代码:

#include <stdio.h>
#include<stack>
using namespace std;
char str[220]; //输入字符串
int mat[][5]={
    1,0,0,0,0, //+为1号,运算符优先级矩阵
    1,0,0,0,0,
    1,0,0,0,0,
    1,1,1,0,0,
    1,1,1,0,0
};
stack<int> op; //运算符栈,保存运算符编号
stack<double> in; //数字栈

//是否是运算符,编号/数值,遍历到的字符串下标
void getOp(bool &reto, int &retn, int &i)
{
    //遍历第一个字符,运算符为空,人为添加编号为0的标记
    if(i==0 && op.empty()==true) 
    {
        reto = true;
        retn = 0;
        return;
    }
    if(str[i]==0)
    {
        reto = true;
        retn = 0;
        return;
    }
    if(str[i]>='0' && str[i]<='9')
    {
        reto = false;
    }
    else
    {
        reto = true;
        if(str[i]=='+')
           retn = 1;
        else if(str[i]=='-')
            retn = 2;
        else if(str[i]=='*')
            retn = 3;
        else if(str[i]=='/')
            retn = 4;
        i+=2;//跳过该运算字符和后面的空格
        return;
    }
    //返回结果是数字
    retn = 0;
    for(;str[i]!=' ' && str[i]!='0';i++)
    {
        //计算当前连续数字字符表示的数值
        retn *=10;
        retn +=str[i]-'0';
    }
    if(str[i]==' ')
    {
        //表示字符串还未遍历完
            i++; //跳过空格
    }
    return;

}
int main () {
    while(scanf("%s",str)!=EOF)
    {
        if(str[0]=='0' && str[1]==0) break;
        bool retop;
        int retnum;
        int idx = 0;
        //清空数字和符号栈
        while(!op.empty()) op.pop();
        while(!in.empty()) in.pop();

        //循环遍历表达式字符串
        while(true)
        {
            getOp(retop,retnum,idx);
            if(retop==false)
            {
                in.push(double(retnum));
            }else{
                double tmp;
                if(op.empty()==true || mat[retnum][op.top()]==1)
                {
                    op.push(retnum);
                }else{
                    while(mat[retnum][op.top()]==0)
                    {
                        //重复循环
                        int ret = op.top();//保存栈顶运算符
                        op.pop();
                        double b = in.top();
                        in.pop();
                        double a = in.top();
                        in.pop();
                        if(ret==1) tmp = a+b;
                        else if(ret==2) tmp = a-b;
                        else if(ret ==3) tmp = a*b;
                        else tmp = a/b;
                        in.push(tmp);
                    }
                    op.push(retnum);//讲当前运算符压入栈中
                }
            }

           if(op.size()==2 && op.top()==0) break; //表达式求值结束
        }
        printf("%.2f\n",in.top());
    }
    return 0;
}

题目三:
堆栈的使用
这里注意一下字符的输入

#include<stdio.h>
#include<stack>
using namespace std;

int main()
{
    int n;
    char c;
    int num;
    while(scanf("%d",&n)!=EOF)
    {
        stack<int> S;
        for(int i=0;i<n;i++)
        {
            scanf("%c",&c);
            if(c=='P')
            {
                scanf("%d",&num);
                S.push(num);
            }else if(c=='O')
            {
                if(!S.empty())
                    S.pop();
            }else if(c=='A')
            {
                if(S.empty())
                {
                    printf("E\n");
                }
                else
                {
                    printf("%d\n",S.top());
                }
            }
        }
    }
    return 0;
}

题目四:
表达式求值
题目描述:

对于一个不存在括号的表达式进行计算
输入:
存在多种数据,每组数据一行,表达式不存在空格
输出:
输出结果
样例输入:
6/2+3+3*4
样例输出:
18

代码:(还未思考)

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

int main()  
{  
    string data;  
    string numStr = "";  
    while (cin >> data)  
    {  
        data += '#'; //表达式末尾添加结束符#  
        stack<double> num; //存放操作数  
        stack<char> op;   //存放运算符  
        for (int i = 0; data[i]; ++i)  
        {  
            if(isdigit(data[i])) //取到整个数串  
                numStr += data[i];   
            else  
            {  
                num.push(atoi(numStr.c_str())); //数字入栈  
                numStr = "";  
                if (!op.empty()) //只取出乘法或除法运算符  
                {  
                    char c = op.top();  
                    if (c == '*') //处理乘法  
                    {  
                        op.pop();  
                        int b = num.top();num.pop();  
                        int a = num.top();num.pop();  
                        num.push(a*b);  
                    }  
                    if (c == '/') //处理除法  
                    {  
                        op.pop();  
                        int b = num.top();num.pop();  
                        int a = num.top();num.pop();  
                        num.push(a/b);  
                    }  
                }  
                if(data[i] != '#') op.push(data[i]); //当前运算符入栈  
            }  
        }  
        while(!op.empty()) //处理剩余的加减法  
        {  
            char c = op.top();  
            if (c == '+')  
            {  
                op.pop();  
                int b = num.top();num.pop();  
                int a = num.top();num.pop();  
                num.push(a+b);  
            }  
            if (c == '-')  
            {  
                op.pop();  
                int b = num.top();num.pop();  
                int a = num.top();num.pop();  
                num.push(a-b);  
            }  
        }  
        cout << num.top() << endl;  
    }  
    return 0;  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值