栈-表达式计算

数据结构在学校的时候学的不认真,从头开始补吧。。。。
这次记一记表达式计算算法,主要利用堆栈实现,方便起见直接用的stl

算法流程

stack1.png

  首先要将表达式转换为后缀表达式后缀表达式即 不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:(2 + 1) 3 , 即2 1 + 3 。转换成后缀表达式的原因是方便及更有条理的计算。

  后缀表达式的转换过程如下图:
    stack2.png

在转换过程中要注意以下几点:

  1. 在读到末尾'\0'后要注意把运算符堆栈内的剩余元素依次存入后缀表达式。
  2. 在读到一个数字后要将后面剩余的数字也依次存入后缀表达式,并且要最后添加#作为各个数字的分隔符。
  3. 在计算后缀表达式时将读入的数字字符串转换成整数并存入数字堆栈。
  4. 计算后缀表达式时遇到计算符号则从数字堆栈中退出2个数字,计算出值后再存入数字堆栈。

代码

#include <bits/stdc++.h>

using namespace std;
bool tran(char* exp, char* cal);    //转化为后缀表达式
int calculate(char* exp, char* cal);    /**表达式计算**/

int main()
{
    char exp[101], cal[101];
    while(gets(exp))
        cout << calculate(exp, cal) << endl;
    return 0;
}

int calculate(char* exp, char* cal)
{
    tran(exp, cal); //转化为后缀表达式
    cout << cal << endl;

    stack<int> numStack;
    int i = 0;

    while(cal[i] != '\0')
    {
        int res = 0;
        while(cal[i] >= '0' && cal[i] <= '9')   //将表达式中的字符串变为整数
        {
            res = res*10 + (cal[i]-'0');
            i++;
        }

        if(cal[i] == ' ')
        {
            i++;
            numStack.push(res);
        }
        else
        {
            int num1 = numStack.top();
            numStack.pop();
            int num2 = numStack.top();
            numStack.pop();

            switch(cal[i++])
            {
            case '+': numStack.push(num1 + num2); break;
            case '-': numStack.push(num1 - num2); break;
            case '*': numStack.push(num1 * num2); break;
            case '/': numStack.push(num1 / num2); break;
            }
        }
    }
    return (!numStack.empty()) ? numStack.top() : 0;

}

bool tran(char* exp, char* cal)  //将表达式转换为后缀表达式
{
    stack<char> charStack;
    int i = 0;
    int j = 0;
    char ch = exp[0];

    if(!(exp[strlen(exp)-1] >= '0' && exp[strlen(exp)-1] <= '9') ||
        exp[strlen(exp)-1] != ')' ||
        exp[strlen(exp)-1] != ' '
       )
        return false;

    while(ch != '\0')
    {
        switch(ch)
        {
        case '(':
            charStack.push(ch);
            break;

        case '+':
        case '-':
            while(!charStack.empty() && charStack.top() != '(')
            {
                cal[j++] = charStack.top();
                charStack.pop();
            }
            charStack.push(ch);
            break;

        case '*':
        case '/':
            while(!charStack.empty() &&
                  charStack.top() != '(' &&
                  (charStack.top() == '*' || charStack.top() == '/')
                 )
            {
                cal[j++] = charStack.top();
                charStack.pop();
            }
            charStack.push(ch);
            break;

        case ')':
            while(charStack.top() != '(' && !charStack.empty())
            {
                cal[j++] = charStack.top();
                charStack.pop();
            }
            charStack.pop();
            break;

        default:
            if(ch >= '0' && ch <= '9')
            {
                while(ch >= '0' && ch <= '9')
                {
                    cal[j++] = ch;
                    ch = exp[++i];
                }
                i--;
                cal[j++] = ' '; //用#将数隔开,便于计算
            }
            break;
        }
        ch = exp[++i];
    }
    /**在读到末尾'\0'后要注意把运算符堆栈内的剩余元素依次存入后缀表达式。**/
    while(!charStack.empty())
    {
        cal[j++] = charStack.top();
        charStack.pop();
    }
    cal[j] = '\0';
    return true;
}
标签: none