中缀式转后缀式和前缀式及求值详解

一、中缀式转为后缀式   


     (字符栈内首先压入一个'#',作为判断栈是否为空的标志)
    从字符串的左边开始遍历,若是数字就直接输出(其中输出有两种方式1、以字符输出,
    2、以浮点型输出),成为后缀表达式的一部分;若是运算符,则与栈顶的运算符进行
    比较,若 “当前>栈顶,则入栈,当前<=栈顶,则出栈“直至扫描结束,最后把#之前
    的都输出。

样例输入
    2
    1.000+2/4=
    ((1+2)*5+1)/4=

样例输出

    1.000 2 4 / + =
    1 2 + 5 * 1 + 4 / =

//中缀转后缀具体代码
#include <stdio.h>
#include <string.h>
#include <stack>
using namespace std;
stack <char> osta;
char s[1010];
int main()
{
    int T;
    osta.push('#');
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s);
        int len=strlen(s);
        for(int i=0;i<len-1;i++)
        {
            if(s[i]=='(')
                osta.push(s[i]);
            else if(s[i]=='*'||s[i]=='/')
            {
                while(osta.top()=='*'||osta.top()=='/')
                {
                    printf("%c ",osta.top());
                    osta.pop();
                }
                osta.push(s[i]);
            }
            else if(s[i]>='0'&&s[i]<='9')
            {
                while(s[i]>='0'&&s[i]<='9'||s[i]=='.')
                {
                    printf("%c",s[i]);
                    i++;
                }
                i--;
                printf(" ");
            }
            else if(s[i]=='+'||s[i]=='-')
            {
                while(osta.top()!='#'&&osta.top()!='(')
                {
                    printf("%c ",osta.top());
                    osta.pop();
                }
                osta.push(s[i]);
            }
            else if(s[i]==')')
            {
                while(osta.top()!='(')
                {
                    printf("%c ",osta.top());
                    osta.pop();
                }
                osta.pop();
            }            
        }
        while(osta.top()!='#')
        {
            printf("%c ",osta.top());
            osta.pop();
        }
        printf("=\n");
    }
    return 0;
}

    利用后缀式求值


    ”从左到右“扫描后缀表达式,若是数据(因为是字符需进一步处理)则进行处理后直接入栈,
    当遇到运算符时,弹出两个栈顶元素进行相应运算,
将运算结果重新压入栈中,直到扫描
    结束,最后输出栈顶元素即可,并将栈顶元素弹出以免影响下一次运算。


//已知后缀式求值
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <stack>
using namespace std;
stack<double> dsta;
int main()
{
    int T;
    scanf("%d",&T);getchar();
    while(T--)
    {
        
        char s[1005];
        gets(s);
        int len=strlen(s);
        for(int i=0;i<len-1;i++)
        {
            if(s[i]==' ')
                continue;
            else if(s[i]>='0'&&s[i]<='9')
            {
                int K=0,b;
                double v=0;
                while(s[i]>='0'&&s[i]<='9'||s[i]=='.')
                {
                    if(s[i]=='.')
                    {
                        K=1;b=i;
                    }
                    else
                        v=v*10+s[i]-'0';
                    i++;
                }
                i--;
                if(K==1)
                    dsta.push(v/pow(10,i-b));
                else
                    dsta.push(v);
            }
            else
            {
                double a=dsta.top();dsta.pop();
                double b=dsta.top();dsta.pop();
                double c;
                switch(s[i])
                {
                    case '+':c=b+a;break;
                    case '-':c=b-a;break;
                    case '*':c=b*a;break;
                    case '/':c=b/a;break;
                }
                dsta.push(c);
            }
        }
        printf("%.2lf\n",dsta.top());
        dsta.pop();
    }
    return 0;
}

二、中缀式转为前缀式


    (首先在字符栈内压入‘#’,以作为判断栈是否为空的标志)
    从中缀表达式的 ”右边“ 开始扫描,(先入栈最后弹出法定义一个字符栈,当
    扫描时进行处理时,若是数字字符则直接压入栈内,若是右括号直接入栈,若是运算
    符,则与栈顶运算符进行优先级比较,
    若”当前>=栈顶,则入栈,当前<栈顶,则出栈“,若是左括号,则把栈顶是右括号之
    前的全部弹出
,直到扫描结束,最后把#之前的都输出。输出的既是前缀表达式

样例输入
    2
    1+((2+3)*4)-5=
    ((1+2)*5+1)/4=

样例输出
    - + 1 * + 2 3 4 5
    / + * + 1 2 5 1 4

//中缀转前缀代码
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stack>
using namespace std;
stack<char> osta; //用此栈输出的是前缀的逆序表示
stack<char> ostr;//存放逆序的表达式 (先入栈后弹出法)
char s[1005];

//若用ostr栈存放就不必用此函数
void resver(char *str,int L)
{
    int i,j;
    char t;
    for(i=0,j=L-1;i<L/2;i++,j--)
    {
        t=str[i];
        str[i]=str[j];
        str[j]=t;
    }
}
//直接输出的是前缀的逆序,最后
//用栈ostr弹出的是正确的前缀式
int main()
{
    int T;
    scanf("%d",&T);
    getchar();
    osta.push('#');
    ostr.push('#');
    while(T--)
    {
        gets(s);
        int len=strlen(s);
        int i,j;
        printf("逆序的前缀表达式:");
        for(i=len-2;i>=0;i--)
        {
            if(s[i]==')')
                osta.push(s[i]);
            else if(s[i]>='0'&&s[i]<='9')
            {
                char str[20];
                int j=0;
                while(s[i]>='0'&&s[i]<='9'||s[i]=='.')
                {
                    str[j]=s[i];
                    ostr.push(s[i]);
                    i--;j++;
                }
                i++;
                ostr.push(' ');
                str[j]='\0';
                resver(str,j);
                printf("%s ",str);
            }
            else if(s[i]=='+'||s[i]=='-')
            {
                while(osta.top()=='*'||osta.top()=='/')
                {
                    ostr.push(osta.top());
                    ostr.push(' ');
                    printf("%c ",osta.top());
                    osta.pop();
                }
                osta.push(s[i]);
            }
            else if(s[i]=='*'||s[i]=='/')
                osta.push(s[i]);
            else if(s[i]=='(')
            {
                while(osta.top()!=')')
                {
                    ostr.push(osta.top());
                    ostr.push(' ');
                    printf("%c ",osta.top());
                    osta.pop();
                }
                osta.pop();
            }
        }
        while(osta.top()!='#')
        {
            ostr.push(osta.top());
            ostr.push(' ');
            printf("%c ",osta.top());
            osta.pop();
        }
        printf("\n正确的前缀表达式:");
        while(ostr.top()!='#')
        {
            printf("%c",ostr.top());
            ostr.pop();
        }
        printf("\n");
    }
    return 0;
}

    利用前缀式求值


     从”右到左开始扫描”,若是数据字符则进行处理存入字符串中,该数据扫描结束

    后翻转该字符串因为是逆序扫描),并转换成相应数值并压入数据栈中,若是运

    算符,则直接弹出两个数据进行运算,并把结果重新压入栈中,直到扫描结束,最
    后弹出数据栈中的最后一个元素既是结果。


//已知前缀式求值
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stack>
using namespace std;
stack <double> dsta;
char s[1500];
int main()
{
    while(gets(s))
    {
        int len=strlen(s);
        for(int i=len-1;i>=0;i--)
        {
            if(s[i]==' ')
                continue;
            if(s[i]>='0'&&s[i]<='9')
            {
                int v=0;
                if(s[i-1]!=' ')
                {
                    int j=0,a[10];
                    while(s[i]!=' ')
                    {
                        if(s[i]=='.')
                        {
                            i--;
                            continue;                            
                        }
                        a[j]=s[i]-'0';
                        j++;i--;
                    }
                    for(int k=j-1;k>=0;k--)
                        v=v*10+a[k];
                    dsta.push(v/pow(10,j-1));
                }                    
                else
                    dsta.push(s[i]-'0');
            }
            else
            {
                double a=dsta.top();dsta.pop();
                double b=dsta.top();dsta.pop();
                double c;
                switch(s[i])
                {
                    case '+':c=a+b;break;
                    case '-':c=a-b;break;
                    case '*':c=a*b;break;
                    case '/':c=a/b;break;
                }
                dsta.push(c);
            }
        }
        printf("%.2lf\n",dsta.top());
        dsta.pop();
    }
    return 0;
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值