C++逆波兰算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014183456/article/details/84647386

逆波兰表达式又叫做后缀表达式。
在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表示。波兰逻辑学家J.Lukasiewicz于1929年提出了另一种表示表达式的方法,按此方法,每一运算符都置于其运算对象之后,故称为后缀表示式。

   逆波兰是一种十分有用的表达式,它将复杂表达式转换为可以依靠简单的操作得到计算结果的表达式。例如(a+b)*(c+d)转换为ab+cd+*。

它的优势在于只用两种简单操作,入栈和出栈就可以搞定任何普通表达式的运算。
1.如何将一个中序表达式转换成逆波兰表达式:

   首先定义两个栈:S1和S2。S1中存储最终形成的逆波兰表达式,S2将用于暂时存放运算符(在最终形成逆波兰表达式的时候,清空该栈)。

   下面详细说明如何形成一个逆波兰表达式:

   首先要明确各运算符之间的优先级关系,然后从左到右遍历一个给定的中序表达式:

  (1)如果遇到的是数字,将数字压入S1中;

  (2)如果遇到的是左括号,将左括号压入S2中;

  (3)如果遇到的是右括号,将S2中的运算符一直出栈压入S1中,直到遇到左括号,但是该左括号出S2却不入S1;

  (4)如果遇到的是运算符,按照如下规则操作:

(1)如果S2为空,将运算符压入S2中;

(2)如果S2不为空,当前遍历到的运算符优先级不小于S2栈顶运算符,将当前遍历到的运算符压入S2;

(3)如果S2不为空,当前遍历到的运算符优先级小于S2栈顶运算符,将栈顶运算符一直出栈压入S1中,直到栈为空或遇到一个运算符优先 级小于当前遍历到的运算符,此时将当前遍历到的运算符压入S2;

(5)直到遍历完整个中序表达式后,若S2中仍然存在运算符,将这些运算符依次出栈压入S1,直到S2为空;

按照上面5条规则反复操作,最终会在S1中形成需求的逆波兰表达式。

2.利用逆波兰表达式求值

首先定义一个栈:S3,在该栈中存放最终表达式的值。从左到右遍历S1,然后按照如下规则操作S3:

(1)如果遇到的是数字,将数字压入S3中;

(2)如果遇到单目运算符(运算对象只有一个的运算符,如:或(|)、与(&)等),取S3栈顶一个元素进行单目运算,将结果再次压入S3中;

(3)如果遇到双目运算符(运算对象有两个的运算符,如:加(+)、赋值(=)等),取S3栈顶两个元素(先出栈的在右,后出栈的在左)进行 双目运算,将结果再次压入S3中;

按照上面3条规则遍历完S1,那么最后S3中的值就是逆波兰表达式的值了

原文:https://blog.csdn.net/qq_39662044/article/details/76595701

下面是根据这个写的算法:

#include <iostream>
#include <string>
#include <stack>
#include <sstream>
using namespace std;
//using std::string;

int priority(char c)   //优先级
{
   switch(c)
   {
     case '+':
           return 1;
        break;
     case '-':
            return 1;
        break;
     case '*':
           return 2;
        break;
     case '/':
          return 2;
        break;
    default :
        return 0;
   }
}
string printStack(stack<char> str)
{
    string result;
   while(!str.empty())
   {
       result=str.top()+result;
       str.pop();
   }
   return result;
}
string Polish(string str)   //逆波兰表达式
{
    stack<char>S1;
    stack<char>S2;
    for(int i=0;i<str.length();i++)
    {
       char curChar=str[i];
       if((curChar>='0') && (curChar <='9'))                   //如果遇到的是数字,将数字压入S1中
       {
          S1.push(curChar);
       }
       else if(curChar=='(')   //如果遇到的是左括号,将左括号压入S2中
       {
            S2.push(curChar);
       }
       else if(!S2.empty() &&curChar==')')  //如果遇到的是右括号,将S2中的运算符一直出栈压入S1中,直到遇到左括号,但是该左括号出S2却不入S1;
       {
           while(S2.top()!='(')
           {
               S1.push(S2.top());
               S2.pop();
           }
           S2.pop();
       }
       else  //如果遇到的是运算符,按照如下规则操作
       {
           if(!S2.empty()) //如果S2不为空
           {
               if((priority(curChar)>=priority(S2.top())))  //当前遍历到的运算符优先级不小于S2栈顶运算符
                    S2.push(curChar);                       //将当前遍历到的运算符压入S2
                else   //如果S2不为空,当前遍历到的运算符优先级小于S2栈顶运算符,将栈顶运算符一直出栈压入S1中,
                {      // //直到栈为空或遇到一个运算符优先级小于当前遍历到的运算符,此时将当前遍历到的运算符压入S2;
                    while(!S2.empty())
                    {
                         if((priority(curChar)<=priority(S2.top())))
                        {
                          S1.push(S2.top());
                          S2.pop();
                        }
                        else
                            break;

                    }
                    S2.push(curChar);
                }
           }
           else
           {
              S2.push(curChar);   //如果S2为空,将运算符压入S2中
           }
       }

    }
       while(!S2.empty())  //直到遍历完整个中序表达式后,若S2中仍然存在运算符,将这些运算符依次出栈压入S1,直到S2为空;
       {
          S1.push(S2.top());
          S2.pop();
       }
   return  printStack(S1);
}
int cal(string S1)   //计算值
{
   stack<int>S3;
   for(int i=0;i<S1.length();i++)
   {
        char curChar=S1[i];
        int a,b,res;
        if(curChar=='+' || curChar=='-' || curChar =='*' || curChar=='/')
        {
            b=S3.top();  S3.pop();
            a=S3.top();  S3.pop();
            if(curChar=='+')
                res=a+b;
            else if(curChar=='-')
                res=a-b;
            else if(curChar=='*')
                res=a*b;
            else
                res=a/b;

            S3.push(res);
        }
        else
        {

           int temp;
           if(!S3.empty())
           {
              temp=S3.top();S3.pop();
              temp=temp*10+(curChar-'0');
              S3.push(temp);
           }
           else
           {

             S3.push(curChar-'0');
           }

        }
   }
   return S3.top();
}


int main()
{
  //  cout << "Hello world!" << endl;
  string  str;
  int c;
  cout<<"请输入表达式:";
  cin>>str;
  string result=Polish(str);
  cout<<result<<endl;

  cout<<"计算的值是:";
   c=cal(result);
  cout<<c<<endl;
    return 0;
}

逆波兰表达式是正确的,但是计算的值我在codeblocks运行是错误的,但是我在牛客网的运行是正确的,不知道怎么回事。

猜你喜欢

转载自blog.csdn.net/u014183456/article/details/84647386