关于逆波兰式

一个表达式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 }

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

程序待优化。

posted @ 2013-02-28 22:17  生无所息  阅读(401)  评论(0编辑  收藏  举报