zoukankan      html  css  js  c++  java
  • 关于逆波兰式

    一个表达式E的逆波兰式如下定义:

    1. 如果E是一个变量或者常量,E的后缀式是其自身;
    2. 如果E是E1 op E2的形式,则其后缀式是E1' E2' op的形式,其中E1'表示E1的后缀式;
    3. 如果E=(E1),那么E的后缀式与E1相同(换言之,逆波兰式不需要括号来表示优先级);

    将一个普通的中缀表达式exp转换为逆序表达式的一般算法是:

    stack s1,s2; //s1是临时存放运算符的,s2是存放后缀式的

    s1.push('#'); //放入优先级最低的符号

    for x in exp:

        if(x is num):

            y=got(x);        //注意这里got函数里面必须完成x迭代器的前行

    s2.push(y);

        else if(x is op):

        while(x<=s1.top() || s1.top=='('):

          s2.push(s1.pop());

        if(x==')'):

          while(s1.top()!='(')s2.push(s1.pop());

          s1.pop();

        else s1.push(x);

      while(s1.top()!='#')s2.push(s1.pop());

    完成上述步骤后,s2中存放的即是倒序的逆波兰式;

    利用逆波兰式posfix计算:

    stack s;

    doubel lhs,rhs=s.top();

    for x in posfix:

        if(x is op):

        rhs=s.pop();

        lhs=s.pop();

        rhs=calc(lhs,rhs,x);

        s.push(rhs);

      else s.push(x)

    return rhs;

    如果需要计算浮点数,最好将操作符映射成小浮点数;

    无bug的解决方案是先分词,然后用stack存放单词结构,无须映射,更加清晰;

    补上例程:

    View Code
      1 #include <vector>
      2 #include <map>
      3 #include <stack>
      4 #include <iostream>
      5 #include <sstream>
      6 #include <string>
      7 #include <cctype>
      8 using namespace std;
      9 
     10 struct Word
     11 {
     12     Word(char k='n',double v=0):
     13         kind(k),value(v)
     14     {
     15 
     16     }
     17     char kind;
     18     double value;
     19 };
     20 bool isOperator(char k)
     21 {
     22     static char op[]=
     23     {
     24         '+','-','*','/','(',')'
     25     };
     26     int size=sizeof(op)/sizeof(op[0]);
     27     for(int i=0;i!=size;++i)
     28     {
     29         if (k==op[i])
     30         {
     31             return true;
     32         }
     33     }
     34     return false;
     35 }
     36 int split2Words(const string& srcString,vector<Word> &dst)
     37 {
     38     dst.clear();
     39     stringstream ss;
     40     ss<<srcString;
     41     char kindFlag;
     42     double value;
     43     while (ss>>kindFlag)
     44     {
     45         if(isdigit(kindFlag))
     46         {
     47             ss.putback(kindFlag);
     48             ss>>value;
     49             dst.push_back(Word('n',value));
     50         }else if(isOperator(kindFlag))
     51         {
     52             dst.push_back(Word(kindFlag));
     53         }
     54         else
     55         {
     56             return -1;
     57         }
     58     }
     59     return 0;
     60 }
     61 int convert2Posfix(vector<Word> &words)
     62 {
     63     stack<Word> s1,s2;
     64     s1.push('#');
     65     static map<char,char> priority;
     66     if (priority.empty())
     67     {
     68         priority['#']=0;
     69         priority['+']=2;
     70         priority['-']=2;
     71         priority['*']=3;
     72         priority['/']=3;
     73         priority['(']=4;
     74         priority[')']=4;
     75     }
     76     Word current;
     77     for(int i=0;i!=words.size();++i)
     78     {
     79         current=words[i];
     80         if (current.kind=='n')
     81         {
     82             s2.push(current);
     83         }else
     84         {
     85             while(priority[current.kind]<=priority[s1.top().kind] && s1.top().kind!='(')
     86             {
     87                 s2.push(s1.top());
     88                 s1.pop();
     89             }
     90             if (current.kind==')')
     91             {
     92                 while(s1.top().kind!='(')
     93                 {
     94                     s2.push(s1.top());
     95                     s1.pop();
     96                 }
     97                 s1.pop();
     98             }else
     99             {
    100                 s1.push(current);
    101             }
    102         }
    103     }
    104     while(s1.top().kind!='#')
    105     {
    106         s2.push(s1.top());
    107         s1.pop();
    108     }
    109     words.clear();
    110     while (!s2.empty())
    111     {
    112         words.insert(words.begin(),s2.top());
    113         s2.pop();
    114     }
    115     //for (int i=0;i!=words.size();++i)
    116     //{
    117     //    if (words[i].kind=='n')
    118     //    {
    119     //        cout<<words[i].value;
    120     //    }else
    121     //    {
    122     //        cout<<words[i].kind;
    123     //    }
    124     //}
    125     //cout<<endl;
    126     return 0;
    127 }
    128 double calc(double lhs,double rhs,char op)
    129 {
    130     switch (op)
    131     {
    132     case '+':
    133         return lhs+rhs;
    134     case '-':
    135         return lhs-rhs;
    136     case '*':
    137         return lhs*rhs;
    138     case '/':
    139         return lhs/rhs;
    140     default:
    141         break;
    142     }
    143     return 0;
    144 }
    145 double calcPosix(const vector<Word> &words)
    146 {
    147     stack<double> s1;
    148     double lhs,rhs=words[0].value;
    149     for(int i=0;i!=words.size();++i)
    150     {
    151         if (words[i].kind=='n')
    152         {
    153             s1.push(words[i].value);
    154         }else
    155         {
    156             rhs=s1.top();
    157             s1.pop();
    158             lhs=s1.top();
    159             s1.pop();
    160             rhs=calc(lhs,rhs,words[i].kind);
    161             s1.push(rhs);
    162         }
    163     }
    164     return rhs;
    165 }
    166 int main()
    167 {
    168     string expression;
    169     vector<Word> words;
    170     double result;
    171     while(getline(cin,expression))
    172     {    
    173         int flag=split2Words(expression,words);
    174         //if(flag<0) exit(EXIT_FAILTURE);
    175         convert2Posfix(words);
    176         result=calcPosix(words);
    177         cout<<result<<endl;
    178     }
    179 
    180     return 0;
    181 }

    上述例程可以计算含括号的浮点数普通四则运算,但是没有错误处理功能…

    程序待优化。

  • 相关阅读:
    学习人人都是产品经理03
    Excel 自增
    axios中get/post请求方式
    vue本地跨域实现与原理
    于无声处听惊雷Deepin成长小记
    .NET桌面程序混合开发之三:WebView2与JS的深度应用
    跨平台系统的开发方案整理
    .NET桌面程序混合开发之二:在原生WinFrom程序中使用WebView2
    双系统升级Win11小记.md
    .NET桌面程序混合开发之一:Winform+H5,WebView2概览
  • 原文地址:https://www.cnblogs.com/livewithnorest/p/2937841.html
Copyright © 2011-2022 走看看