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

来源:互联网 发布:网络布线施工室分 编辑:程序博客网 时间:2024/06/05 14:27

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

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

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

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
原创粉丝点击