1、中缀式转前缀式:
(1)从左向右读取字符,新建数组suffix用来存储后缀表达式
(2)如果遇到‘(’,入栈,继续读取。
(3)如果遇到‘ )’,将栈顶元素依次出栈存到suffix中,直到栈顶元素为‘(’,此时将栈顶元素出栈,继续读取。
(4)如果遇到运算符,将其与栈顶元素进行比较,如果该运算符优先级小于等于栈顶元素,则将栈顶元素出栈,存到suffix中,直到该运算符大于栈顶元素,将其入栈。
(5)遇到操作数,直接存到suffix中。
(6)读取完后,将栈内剩余所有元素存到suffix中。此时suffix为后缀表达形式。
2、中缀式转后缀式:
(1)从右向左读取字符,新建数组suffix用来存储前缀表达式
(2)如果遇到‘)’,入栈,继续读取。
(3)如果遇到‘ (’,将栈顶元素依次出栈存到suffix中,直到栈顶元素为‘(’,此时将栈顶元素出栈,继续读取。
(4)如果遇到运算符,将其与栈顶元素进行比较,如果该运算符优先级小于栈顶元素,则将栈顶元素出栈,存到suffix中,直到该运算符大于等于栈顶元素,将其入栈。
(5)遇到操作数,直接存到suffix中。
(6)读取完后,将栈内剩余所有元素存到suffix中。此时suffix为前缀表达形式。
3、二者算法比较:
(1)读取顺序不同,转前缀式时从右向左读取,转后缀式时从左向右读取。
(2)运算符入栈时,需要注意比较条件,转后缀时因为是顺序读取字符串,所以当栈顶运算级大于时必须要先出栈,保证后面计算时能先进行这个元素,同理等于的时候也是如此。但是转前缀的时候有个陷阱,就是当运算符级别一致的时候,因为是从右向左读取的,所以此时不能将其出栈。
(3)括号处理的时候本质一样,都是为了保证括号内的运算大于括号外的运算。
练习:NYOJ409
#include
#include
#include
#include
using namespace std;
int weight(char a)
{
if(a == '+' || a == '-')
return 1;
else if(a == '*' || a == '/')
return 2;
else
return 0;
}
int midtosuffix(string &s1,string &s2)
{
int i = 0;
stack s;
s.push('#');
while(i < s1.length()-1)
{
if(s1[i] == '(')
{
s.push(s1[i]);
i++;
}
else if(s1[i] == ')')
{
while(s.top() != '(')
{
s2 += s.top();
s2 += ' ';
s.pop();
}
s.pop();
i++;
}
else if(s1[i] == '+' || s1[i] == '-' || s1[i] == '*' || s1[i] == '/')
{
while(weight(s.top()) >= weight(s1[i]) ) //一定注意此句,不是if,因为可能会有多个运算符在栈内,要判断完
{
s2 += s.top();
s2 += ' ';
s.pop();
}
s.push(s1[i]);
i++;
}
else
{
while(s1[i] >= '0' && s1[i] <= '9' || s1[i] == '.')
{
s2 += s1[i++];
}
s2 += ' ';
}
}
while(s.top() != '#')
{
s2 += s.top();
s2 += ' ';
s.pop();
}
}
int midtoprefix(string &s1,string &s3)
{
int i = s1.length()-2;
stack s;
s.push('#');
while(i >= 0)
{
//cout< weight(s1[i])) //一定注意此句,不是if,因为可能会有多个运算符在栈内,要判断完
//区别于转后缀,且优先级比较的时候只能是大于
{
s3 += s.top();
s3 += ' ';
s.pop();
}
s.push(s1[i]);
i--;
}
else
{
while(s1[i] >= '0' && s1[i] <= '9' || s1[i] == '.')
{
s3 += s1[i--];
}
s3 += ' ';
}
}
while(s.top() != '#')
{
s3 += s.top();
s3 += ' ';
s.pop();
}
}
int midtoprefix1(string &s1,string &s3)
{
int i = s1.length()-2;
stack s;
s.push('#');
while(i >= 0)
{
//cout<= weight(s1[i])) //一定注意此句,不是if,因为可能会有多个运算符在栈内,要判断完
//此处这样做为错误做法
{
s3 += s.top();
s3 += ' ';
s.pop();
}
s.push(s1[i]);
i--;
}
else
{
while(s1[i] >= '0' && s1[i] <= '9' || s1[i] == '.')
{
s3 += s1[i--];
}
s3 += ' ';
}
}
while(s.top() != '#')
{
s3 += s.top();
s3 += ' ';
s.pop();
}
}
double cal(string s2)
{
stack s;
int i = 0;
double x,y;
while(i < s2.length())
{
if(s2[i] == ' ')
{
i++;
continue;
}
if(s2[i] == '+')
{
x = s.top();
s.pop();
x += s.top();
s.pop();
i++;
}
else if(s2[i] == '-')
{
x = s.top();
s.pop();
x = s.top() - x;
s.pop();
i++;
}
else if(s2[i] == '*')
{
x = s.top();
s.pop();
x *= s.top();
s.pop();
i++;
}
else if(s2[i] == '/')
{
x = s.top();
s.pop();
x = s.top()/x;
s.pop();
i++;
}
else
{
x = 0;
while(s2[i] >= '0' && s2[i] <= '9')
{
x *= 10;
x += s2[i]-'0';
i++;
}
if(s2[i] == '.')
{
y = 0;
double k = 10.00;
i++;
while(s2[i] >= '0' && s2[i] <= '9')
{
y += (s2[i]-'0')/k;
k *= 10.00;
i++;
}
x += y;
}
}
s.push(x);
}
return s.top();
}
int main()
{
string s1,s2,s3,st;
freopen("409test.txt","w",stdout);
int t;
int i,x;
scanf("%d",&t);
while(t--)
{
cin>>s1;
s2 = "";
s3 = "";
st = "";
midtoprefix(s1,s3);
for(i = s3.length()-2; i >= 0; i--)
cout<= 0; i--)
cout<