zoukankan      html  css  js  c++  java
  • 表达式的求值

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

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

    输入的前提假设:

                            (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;
    }

       

  • 相关阅读:
    高性能TcpServer(Java)
    高性能TcpServer(C#)
    高性能TcpServer(C#)
    高性能TcpServer(C#)
    高性能TcpServer(C#)
    高性能TcpServer(C#)
    高性能TcpServer(C#)
    MySQL连表Update修改数据
    windows服务器安装安全狗时服务名如何填写
    织梦ckeditor编辑器 通过修改js去除img标签内的width和height样式
  • 原文地址:https://www.cnblogs.com/dean-SunPeishuai/p/10622446.html
Copyright © 2011-2022 走看看