C++算法计算表达式(中缀表达式转后缀表达式)

              算法:中缀表达式转后缀表达式(想看全部代码直接翻到底部)

众所周知,在编程里面,直接用中缀表达式求值是不方便的,so咱们将中缀转化为后缀再求值。
平时咱们使用的表达式为中缀表达式:
如:a+b*(c-d);
运算符本身具有优先级,存在括号优先级,编程时考虑的情况多样,代码也不简洁。
So咱们推出一个后缀表达式:
如上面表达式转换成后缀abcd-*+;
只存在操作符和运算符。
中缀转后缀方法(采用栈来实现):中缀转后缀步骤图
咱们会发现,数字如果是两位的话,与运算符不太好隔离。这就有二种解决办法:
1.直接定义一个结构体栈,里面含数组和字符数组,咱们可间字符数组里将表示数字的字符定义成‘0’字符以便判断。
如19+2+5;它的字符数组可以为0+0+0。
2.就是直接定义两个数组,一个是存数字一个是存字符。

    string a;
    queue<int> s2;
    cin>>a;
    int t[50]= {0};
    char ch[50];
    int c=a.length();
    int i=0,j=0,k=0;
    for(i=0;i<c;i++)
    {
        ch[i]='0';
    }
    //分为两个数组
    for(i=0; i<c; i++)
    {
        if(a[i]>='0'&&a[i]<='9')
        {
            t[j]=t[j]*10+(a[i]-'0');
            if(a[i+1]<'0'||a[i+1]>'9')
            {
                j++;
            }
        }
        else
        {
            ch[j]=a[i];
            j++;
        }
    }

分隔解决了,然后是中缀转后缀(按照上述图片步骤)

stack<int> s;//临时存符号栈
    int i,j,f;
    int m,n;//比较优先级
    int n1=a.length();
    for(i=0; i<n1; i++)
    {
        if(ch[i]=='0')
        {
            s2.push(i);
        }
        else if(ch[i]!='0'&&s.empty()==1&&ch[i]!='(')
        {
            s.push(i);
        }
        else if(ch[i]=='(')
        {
            s.push(i);
            //适用()里只有一个算术符号
            while(ch[i]!=')')
            {
                i++;
                if(ch[i]=='0')
                {
                    s2.push(i);
                }
                else if(ch[i]!='0')
                {
                    s.push(i);
                }
            }
            s.pop();//')'出栈
            int f=s.top();//临时顶部符号下标
            while(ch[f]!='(')
            {
                s2.push(f);
                s.pop();
                f=s.top();
            }
            s.pop();
        }
        else if(s.empty()==0&&ch[i]!='0')
        {
            f=s.top();
            m=getpriority(ch[f]);
            n=getpriority(ch[i]);
            while(m>=n&&s.empty()!=1)//注意s栈要不为空
            {
                s2.push(f);
                s.pop();
                //栈不为空的时候取顶
                if(s.empty()!=1)
                {
                    f=s.top();
                    m=getpriority(ch[f]);
                }
            }
            s.push(i);
        }
    }
    while(s.empty()==0)
    {
        f=s.top();
        s2.push(f);
        s.pop();
    }

后缀求值:
1.将已经完成的后缀表达式队列出列一个,进入新栈。
2.依次出列进栈,遇到运算符,栈顶的两位出栈运算,运算顺序:第二位出栈+运算符+第一位出栈。运算结果入栈。
3.直到队列为空,栈里只有一个元素,取栈顶输出结果。
代码:

stack<int> s;//后缀表达式在此栈里计算
    int index=s2.front();
    int sm,i,j;
    s.push(t[index]);
    //栈中一个元素入另一个栈,一进一删
    s2.pop();
    while(s.empty()!=1)
    {
        index=s2.front();
        s2.pop();
        if(ch[index]=='0')
        {
            s.push(t[index]);
        }
        else
        {
            if(ch[index]=='+')
            {
                i=s.top();
                s.pop();
                j=s.top();
                s.pop();
                sm=i+j;
                s.push(sm);
            }
            else if(ch[index]=='-')
            {
                i=s.top();
                s.pop();
                j=s.top();
                s.pop();
                sm=j-i;
                s.push(sm);
            }
            else if(ch[index]=='/')
            {
                i=s.top();
                s.pop();
                j=s.top();
                s.pop();
                sm=j/i;
                s.push(sm);
            }
            else if(ch[index]=='*')
            {
                i=s.top();
                s.pop();
                j=s.top();
                s.pop();
                sm=j*i;
                s.push(sm);
            }
        }
        if(s2.empty()==1)
        {
            cout<<s.top()<<endl;
            s.pop();
        }
    }`
全部代码:
#include <iostream>
#include<stack>
#include<queue>
using namespace std;
int getpriority(char v)
{
    switch(v)
    {
    case'+':
    case'-':
        return 1;
    case'*':
    case'/':
        return 2;
    default:
        return 0;
    }
}

/*中缀转后缀*/
void inturnafter(string a,int t[],char ch[],queue<int> &s2)
{
    stack<int> s;//临时存符号栈
    int i,j,f;
    int m,n;//比较优先级
    int n1=a.length();
    for(i=0; i<n1; i++)
    {
        if(ch[i]=='0')
        {
            s2.push(i);
        }
        else if(ch[i]!='0'&&s.empty()==1&&ch[i]!='(')
        {
            s.push(i);
        }
        else if(ch[i]=='(')
        {
            s.push(i);
            //适用()里只有一个算术符号
            while(ch[i]!=')')
            {
                i++;
                if(ch[i]=='0')
                {
                    s2.push(i);
                }
                else if(ch[i]!='0')
                {
                    s.push(i);
                }
            }
            s.pop();//')'出栈
            int f=s.top();//临时顶部符号下标
            while(ch[f]!='(')
            {
                s2.push(f);
                s.pop();
                f=s.top();
            }
            s.pop();
        }
        else if(s.empty()==0&&ch[i]!='0')
        {
            f=s.top();
            m=getpriority(ch[f]);
            n=getpriority(ch[i]);
            while(m>=n&&s.empty()!=1)//注意s栈要不为空
            {
                s2.push(f);
                s.pop();
                //栈不为空的时候取顶
                if(s.empty()!=1)
                {
                    f=s.top();
                    m=getpriority(ch[f]);
                }
            }
            s.push(i);
        }
    }
    while(s.empty()==0)
    {
        f=s.top();
        s2.push(f);
        s.pop();
    }
}
/*后缀计算*/
void getvalue(queue<int> s2,int t[],char ch[])
{
    stack<int> s;//后缀表达式在此栈里计算
    int index=s2.front();
    int sm,i,j;
    s.push(t[index]);
    //栈中一个元素入另一个栈,一进一删
    s2.pop();
    while(s.empty()!=1)
    {
        index=s2.front();
        s2.pop();
        if(ch[index]=='0')
        {
            s.push(t[index]);
        }
        else
        {
            if(ch[index]=='+')
            {
                i=s.top();
                s.pop();
                j=s.top();
                s.pop();
                sm=i+j;
                s.push(sm);
            }
            else if(ch[index]=='-')
            {
                i=s.top();
                s.pop();
                j=s.top();
                s.pop();
                sm=j-i;
                s.push(sm);
            }
            else if(ch[index]=='/')
            {
                i=s.top();
                s.pop();
                j=s.top();
                s.pop();
                sm=j/i;
                s.push(sm);
            }
            else if(ch[index]=='*')
            {
                i=s.top();
                s.pop();
                j=s.top();
                s.pop();
                sm=j*i;
                s.push(sm);
            }
        }
        if(s2.empty()==1)
        {
            cout<<s.top()<<endl;
            s.pop();
        }
    }
}

int main()
{
    string a;
    queue<int> s2;
    cin>>a;
    int t[50]= {0};
    char ch[50];
    int c=a.length();
    int i=0,j=0,k=0;
    for(i=0;i<c;i++)
    {
        ch[i]='0';
    }
    //分为两个数组
    for(i=0; i<c; i++)
    {
        if(a[i]>='0'&&a[i]<='9')
        {
            t[j]=t[j]*10+(a[i]-'0');
            if(a[i+1]<'0'||a[i+1]>'9')
            {
                j++;
            }
        }
        else
        {
            ch[j]=a[i];
            j++;
        }
    }
    inturnafter(a,t,ch,s2);
    getvalue(s2,t,ch);
    return 0;
}

  • 9
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
中缀表达式转后缀表达式,是一种运算符写在操作数之后的表达式表示方法。下面是一个将中缀表达式转换为后缀表达式算法: 1. 创建一个(称为运算符)和一个空字符串(用于存储后缀表达式)。 2. 从左到右扫描中缀表达式的每个元素。 3. 如果遇到操作数(即数字),则将其直接附加到后缀表达式的末尾。 4. 如果遇到操作符,检查运算符顶元素: a. 如果运算符为空,或者顶元素是左括号"(",则将该操作符入。 b. 如果当前的操作符比运算符顶元素优先级高,则将该操作符入。 c. 如果当前的操作符比运算符顶元素优先级低或相等,则将运算符顶元素弹出并附加到后缀表达式的末尾,直到当前的操作符的优先级高于顶元素。 5. 如果遇到左括号"(",则将其入。 6. 如果遇到右括号")",则弹出运算符的元素并附加到后缀表达式的末尾,直到弹出一个左括号"("。 7. 将中缀表达式扫描完毕后,如果运算符不为空,则将中的所有元素依次弹出并附加到后缀表达式的末尾。 例如,对于中缀表达式"c = a + b * ( d * e + f ) - g",根据上述算法转换为后缀表达式为:"c a b d e * f + * + g -"。 注意:以上算法没有考虑操作符的结合性,如果需要添加结合性的支持,还需对算法进行适当修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值