中缀表达式转化为后缀表达式、后缀表达式求解(栈)

计算器我们都实现了很多了,但是,我们写的计算器都是求解两个操作数的,并不能求解一个表达式,如今栈已经学完了,那么我们可不可以使用栈来实现表达式的求解呢?

我们数学上求解一个表达式是如何进行的,有括号的先求括号内部的,之后先算乘除,再算加减。现在如果来实现一个这样可以求解表达式的计算器,怎样进行呢?

首先是将中缀表达式转化为后缀表达式,具体的规则如下:

1、遇到操作数,直接输出;
2、栈为空时,遇到运算符,入栈;
3、遇到左括号,将其入栈;
4、遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出;
5、遇到其他运算符’+”-”*”/’时,弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈;
6、最终将栈中的元素依次出栈,输出。

之后就是后缀表达式的求解了,大致是这样的:

扫描后缀表达式, 如果是数字,则让其进栈; 若为操作符,则从栈中取出两个操作数,先取出的作为右操作数,后取出的作为左操作数,然后进行该操作符的运算,并使其结果入栈。 重复上述过程,直至表达式扫描完成。 最终栈中只留一个元素,就是表达式结果。

下面是具体的实现代码:

#include<iostream>
using namespace std;

#include<assert.h>
#include<stack>

//获取操作符的优先级
int GetPriority(char ch, int flag)//flag为1时表示栈内优先级  flag为0表示栈外优先级
{
    if (ch == '+' || ch == '-')
    {
        if (flag)
        {
            return 3;
        }
        else
        {
            return 2;
        }
    }
    else if (ch == '*' || ch == '/' || ch == '%')
    {
        if (flag)
        {
            return 5;
        }
        else
        {
            return 4;
        }
    }
    else if (ch == '(')
    {
        if (flag)
        {
            return 1;
        }
        else
        {
            return 6;
        }       
    }
    else if (ch == ')')
    {
        if (flag)
        {
            return 6;
        }
        else
        {
            return 1;
        }
    }
}

//中缀表达式转化后缀表达式
void InfixToPostfix(char *dest, char*src)
{
    assert(dest);
    assert(src);

    stack<char> s;//保存操作符,使其按照优先级从大到小输出
    char* _cur = src;//用一个指针指向中缀表达式
    char* _temp = dest;//用指针指向存储后缀表达式的空间

    while (*_cur != '\0')
    {
        if (*_cur >= '0' && *_cur <= '9')//如果是数字字符,那么保存
        {
            *_temp++ = *_cur;
            _cur++;
            continue;
        }

        //如果是操作符,那么分情况讨论
        else if (*_cur == '+' ||* _cur == '-' || *_cur == '*' || *_cur == '/' || *_cur == '%' || *_cur == '(' || *_cur == ')')
        {
            if (s.empty())//
            {
                s.push(*_cur);
                _cur++;
            }
            else
            {
                if (*_cur == ')')
                {
                    while (s.top() != '(')
                    {
                        *_temp++ = s.top();
                        s.pop();
                    }
                    s.pop();//删除栈顶的‘(’
                    *_cur++;
                }

                //如果当前操作符的优先级大于栈顶元素的优先级,将当前操作符入栈
                if (GetPriority(*_cur, 0) > GetPriority(s.top(), 1))
                {
                    s.push(*_cur);
                    _cur++;
                }
                else
                {
                    while (!s.empty() && GetPriority(*_cur, 0) < GetPriority(s.top(), 1))
                    {
                        *_temp++ = s.top();
                        s.pop();
                    }
                    s.push(*_cur);
                    _cur++;
                }
            }
        }
        else//跳过空格
        {
            *_temp++ = *_cur++;
        }
    }

    //将栈内剩余元素放入表达式
    while (!s.empty())
    {
        *_temp++ = s.top();
        s.pop();
    }
}

//后缀表达式求值(计算器)
int Calculate(char *_postfix,char*_infix)
{
    InfixToPostfix(_postfix, _infix);

    stack<int> s;//注意前后两个栈的使用用途不同,实例化也不同
    char*_cur = _postfix;
    int temp = 0;//保存数字字符转化后的数字
    int res = 0;//保存运算结果

    while (*_cur != '\0')
    {
        if (*_cur >= '0'&&*_cur <= '9')
        {
            res = 0;
            while (!isspace(*_cur) && *_cur >= '0'&&*_cur <= '9')
            {
                temp = *_cur - '0';//将数字字符转化为数字
                res = res * 10 + temp;//  例如:12
                _cur++;
            }
            s.push(res);
        }
        else if (*_cur == '+' || *_cur == '-' || *_cur == '*' || *_cur == '/' || *_cur == '%')
        {
            int right = s.top();//先取出来的是右操作数
            s.pop();
            int left = s.top();
            s.pop();

            switch (*_cur)
            {
            case '+':
                s.push(left + right);
                break;
            case '-':
                s.push(left - right);
                break;
            case '*':
                s.push(left * right);
                break;
            case '/':
                if (right)
                {
                    s.push(left / right);
                    break;
                }
            case '%':
                s.push(left % right);
                break;
            }
            _cur++;
        }
        else//跳过空格
        {
            _cur++;
        }
    }
    if (!s.empty())
    {
        res = s.top();
        s.pop();
        return res;
    }
}

void FunTest()
{
    char* _infix = "12 * (3 + 4) - 6 + 8 / 2 ";
    char _postfix[20] = {};
    int result = Calculate(_postfix, _infix);
    cout <<result << endl;
}

int main()
{
    FunTest();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值