表达式的求值

   计算中缀表达式是一个特别经典的关于栈的算法题,几乎所有的数据结构教材中都会涉及,而且很多公司面试或者笔试的时候会把这道题作为一个考点。因此,他的重要程度就不言而喻,下面 是关于表达式求值的一个总结。

题目:  输入一个中缀表达式计算表达式的结果。

输入的前提假设:

                        (1)只考虑+,-,*,/这四种运算符,中缀表达式只有一种括号:()。

                        (2)输入的中缀表达式只有整数,没有小数。

                        (3)假定输入是合法的。

  为了循序渐进,此处先讨论如何将中缀表达式转化为后缀表达式,在讨论如何计算后最表达式,在前两者的基础上,讨论如何直接计算中缀表达式的结果。对于上面各表达式的概念不再赘述。

一.中缀表达式转化为后缀表达式

      中缀表达式转化为后缀表达式式需要一个临时栈S暂存运算符。

首先将各运算符的优先级排列,(数字越大优先级越高):

1:(

2:+ -

3:* /

4.:)

对输入的中缀表达式从左到右遍历:

伪代码:

           (1)如果遇到数字,直接添加到后缀表达式末尾。

           (2)如果遇到+ - * /:

              先判断栈是否为空。若是,则将此运算压入栈。若不是,则查看当前 栈顶元素。若栈顶元素的优先级大于或等于此操作符级别,则弹出栈顶元素,将栈顶元素添加到后缀表达式后面,并继续上面的判断。如果不满足上述的判断,或栈为空,将这个运算符入栈。

            (3)如果遇到左括号,直接入栈。如果遇到右括号,弹出左括号前的所有操作符,并将左括号弹出。(右括号不如栈)

              (4)字符遍历结束,如果栈不为空,则弹出栈中所有的操作符,将他们添加到后缀表达式的末尾,知道栈为空。

二.计算后缀表达式

伪代码:            准备一个数字栈,从左到右扫描表达式,如果是数字就入栈。如果是符号,从数字栈中弹出两个数字,第一个取出的数字为右运算数,第二个为左运算数,进行运算。然后将运算结果放入数字栈中,如此反复直到读完整个表达式,留在数字栈中的数字就是最终结果。

默认:输入的表达式中的所有的的数都是0——9的 整数,运算结果也为整数。

#include<bits/stdc++.h>
using namespace std;
int Get_Priority(char ch)
{
    if(ch=='(') return 1;
    else if(ch=='-'||ch=='+')  return 2;
    else if(ch=='*'||ch=='/')  return 3;
    else return 4;
}

/*     中缀表达式转后缀表达式     */
string Get_Hou(string s)
{
    stack<char>My_Stack;
    int size=s.size();
    int i=0;
    string res="";///用于保存转化后的结果
    char temp;
    while(i<size)
    {
        ///若为数字直接添加到后缀表达式的后面
        if(s[i]>='0'&&s[i]<='9')
        {
            res.push_back(s[i]);
        }
        else if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/')
        {
            if(My_Stack.empty())///若栈为空,直接将运算符进栈
            {
                My_Stack.push(s[i]);
            }
            else///否者若栈顶的优先级大于或等于当前的优先级,重复出栈并加入到后缀表达式末尾
            {
                while(!My_Stack.empty())
                {
                  temp=My_Stack.top();
                  if(Get_Priority(temp)>=Get_Priority(s[i]))
                  {
                    res.push_back(temp);
                    My_Stack.pop();
                  }
                  else break;
                }
                My_Stack.push(s[i]);///将当前运算符进栈
            }
        }
        else
        {
            if(s[i]=='(') My_Stack.push(s[i]); ///若为做左括号直接进栈
           else///否则,将栈中的元素全部出栈知道遇见左括号
           {
             while(My_Stack.top()!='(')
             {
                temp=My_Stack.top();
                res.push_back(temp);
                My_Stack.pop();
             }
              My_Stack.pop();///删除左括号后缀表达式和前缀表达式不存在括号,位置即体现了优先级
          }
        }
        i++;
    }
    ///遍历完后若栈非空弹出所有的元素
    while(!My_Stack.empty())
    {
                temp=My_Stack.top();
                res.push_back(temp);
                My_Stack.pop();
    }
    return res;
}

/*      计算后缀表达式         */
int calculate(string s)
{
    stack<int>My_Stack;
    int size=s.size();
    int num1,num2,num3;
    for(int i=0;i<size;i++)
    {
        if(s[i]>='0'&&s[i]<='9')
        {
            My_Stack.push(s[i]-'0');
        }
        else
        {
            num2=My_Stack.top();
            My_Stack.pop();
            num1=My_Stack.top();
            My_Stack.pop();

            switch(s[i])
            {
             case '+':
                   num3=num1+num2;
                   break;
             case '-':
                   num3=num1-num2;
                   break;
             case '*':
                    num3=num1*num2;
                    break;
             case '/':
                    num3=num1/num2;
                    break;
            }
            My_Stack.push(num3);
        }
    }
    return My_Stack.top();
}
int main()
{
    string s="1+(2-3)*4+4/2";
    cout<<"中缀表达式:"<<endl<<s<<endl;
    string res=Get_Hou(s);
    cout<<"后缀表达式:"<<endl<<res<<endl;
    int num_res=calculate(res);
    cout <<"后缀表达式计算结果:"<< endl << num_res << endl;
    return 0;
}

参考博客,此段代码摘自:https://blog.csdn.net/sinat_27908213/article/details/80273557

#include<iostream>
#include<string>
#include<stack>
 
using namespace std;
 
int getPriority(char ch)
{
    //获取优先级
    if (ch == '(') return 1;
    else if (ch == '+' || ch == '-') return 2;
    else if (ch == '*' || ch == '/') return 3;
    else return 4;
}
 
void calculate(stack<double> &mystack, char operation)
{
    double num1, num2, num3;
    num2 = mystack.top();
    mystack.pop();
    num1 = mystack.top();
    mystack.pop();
    if (operation == '+') {
        num3 = num1 + num2;
    }
    else if (operation == '-') {
        num3 = num1 - num2;
    }
    else if (operation == '*') {
        num3 = num1 * num2;
    }
    else if (operation == '/') {
        num3 = num1 / num2;
    }
 
    mystack.push(num3);
}
 
double calculator(string str)
{
    //计算中缀表达式,默认输入是合法的
    stack<double> mystack_number;
    stack<char> mystack_operation;
    int i = 0, j;
    int size = str.size();
    char tmp_operation;
    string tmp_num;
    while (i < size) {
        if (str[i] >= '0' && str[i] <= '9') {
            j = i;
            while (j < size && str[j] >= '0' && str[j] <= '9') { j++; }
            tmp_num = str.substr(i, j - i);
            mystack_number.push(atoi(tmp_num.c_str()));
            i = j;
        }
        else if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/') {
            if (mystack_operation.empty()) {
                mystack_operation.push(str[i]);
            }
            else {
                while (!mystack_operation.empty()) {
                    tmp_operation = mystack_operation.top();
                    if (getPriority(tmp_operation) >= getPriority(str[i])) {
                        //计算
                        calculate(mystack_number, tmp_operation);
                        mystack_operation.pop();
                    }
                    else break;
                }
                mystack_operation.push(str[i]);
            }
            i++;
        }
        else {
            if (str[i] == '(') mystack_operation.push(str[i]);
            else {
                while (mystack_operation.top() != '(') {
                    tmp_operation = mystack_operation.top();
                    //计算
                    calculate(mystack_number, tmp_operation);
                    mystack_operation.pop();
                }
                mystack_operation.pop();
            }
            i++;
        }
 
    }
    //遍历完后,若栈非空,弹出所有元素
    while (!mystack_operation.empty()) {
        tmp_operation = mystack_operation.top();
        //计算
        calculate(mystack_number, tmp_operation);
        mystack_operation.pop();
    }
    return mystack_number.top();
}
 
int main()
{
    string str = "1+(2-3)*4+10/2+2*2+2+2/5";
    cout << "中缀表达式为:" << endl << str << endl;
    double num_res = calculator(str);
    cout << "计算结果:" << endl << num_res << endl;
    system("pause");
    return 0;
}

   

猜你喜欢

转载自www.cnblogs.com/dean-SunPeishuai/p/10622446.html