中缀表达式转后缀表达式遵循以下原则:
1.遇到操作数,直接输出;
2.栈为空时,遇到运算符,入栈;
3.遇到左括号,将其入栈;
4.遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出;
5.遇到其他运算符’+”-”*”/’时,弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈;
6.最终将栈中的元素依次出栈,输出。
经过上面的步骤,得到的输出既是转换得到的后缀表达式。
举例:a+b*c+(d*e+f)g ———> abc*+de*f+g*+
图示上述过程:
因为比较懒,而刚好在网上看到画的还不错的图,所以就直接贴过来了哦。希望作者不要怪罪哦。。。
遇到a,直接输出:
遇到+,此时栈为空,入栈:
遇到b,直接输出:
遇到*,优先级大于栈顶符号优先级,入栈:
遇到c,输出:
到+,目前站内的与+优先级都大于或等于它,因此将栈内的,+依次弹出并且输出,并且将遇到的这个+入栈:
遇到(,将其入栈:
遇到d,直接输出:
遇到*
,由于的优先级高于处在栈中的(,因此入栈:
遇到e,直接输出:
遇到+,栈顶的优先级高于+,但是栈内的(低于+,将出栈输出,+入栈:
遇到f,直接输出:
遇到),弹出栈顶元素并且输出,直到弹出(才结束,在这里也就是弹出+输出,弹出(不输出:
遇到*,
优先级高于栈顶+,将*入栈
遇到g,直接输出: :
此时已经没有新的字符了,依次出栈并输出操作直到栈为空:
二. 后缀表达式求值
从左往右扫描后缀表达式,遇到操作数入栈,遇到运算符、弹出两个操作数、计算结果并将结果入栈( 注:先弹出的为右操作数,后弹出的为左操作数),循环以上过程,知道扫描完后缀表达式,此时栈中的数即为运算结果。
/* C++实现中缀表达式转后缀表达式并求值 */
#include <iostream>
using namespace std;
const int MaxLen = 100;
//类的定义
class zh
{
private:
int n; // 结果
char str[MaxLen]; // 存中缀表达式
char exp[MaxLen]; // 存后缀表达式
char st[MaxLen]; // 临时栈
public:
zh() // 构造函数 - 初始化中缀表达式
{
cout << "请输入中缀表达式:";
cin >> str;
cout << endl;
}
bool trans(); // 中缀转后缀,并将后缀存入exp中
bool CompValue(); // 利用后缀求值
void disp_exp(); // 输出后缀表达式
int Get_n() { return n ;} // return 结果
} ;
//中缀转后缀,并将后缀存入exp中
bool zh::trans()
{
char ch;
int i = 0, t = 0, top = -1; //t - exp下标, top - st的下标, i - str的下标
while( (ch = str[i++]) != '\0' )
{
if( ch >= '0' && ch <= '9' ) //判断为数字
{
exp[t] = ch;
t++;
while( (ch = str[i++]) != '\0' && ch >= '0' && ch <= '9' )
{
exp[t] = ch;
t++;
}
i--;
exp[t] = '#'; // 数字结束标识符
t++;
}
else if( ch == '(' ) //左括号入栈
{
top++;
st[top] = ch;
}
else if( ch == ')' ) // 右括号输出栈中左括号以前的所有运算符
{
while( st[top] != '(' ) // 输出栈中左括号以前的所有运算符
{
exp[t] = st[top];
top--;
t++;
}
top--; //与之匹配的左括号弹出
}
else if( ch == '+' || ch == '-' ) //当扫描到运算符时,从临时栈中弹出优先级大于等于当前运算符的
{ //运算符,注:圆括号的优先级最高
while( top >= 0 && st[top] != '(' )
{
while( st[top] == '*' || st[top] == '/' || st[top] == '+' || st[top] == '-' )
{
exp[t] = st[top];
top--;
t++;
}
}
top++;
st[top] = ch;
}
else if( ch == '*' || ch == '/' ) // 若为运算符 * 或 /
{
while( top >= 0 && st[top] != '(' ) // 弹出st栈顶位置的 * 或 /
{
while( st[top] == '*' || st[top] == '/' )
{
exp[t] = st[top];
top--;
t++;
}
}
top++;
st[top] = ch;
}
}
while( top >= 0 ) // 当扫描完运算式时,将此时栈中的所有运算符弹出
{
exp[t] = st[top];
t++;
top--;
}
exp[t] = '\0'; // exp - 按后缀顺序存储运算表达式
return true;
}
//利用后缀表达式计算
//从左向右扫描 exp数组,遇到操作数入栈、遇到运算符弹出操作数
bool zh::CompValue()
{
int d; // 数字字符转数字
char ch;
int t = 0, top = -1;
while( (ch = exp[t++]) != '\0' )
{
if( ch >= '0' && ch <= '9' ) //为数字字符时转换为数字并入栈
{
d = 0;
do
{
d = 10*d + ch-'0';
} while( (ch = exp[t++]) != '#' );
top++;
st[top] = d; //数字进栈
}
else //为运算符时,退栈 - 计算 - 在将结果入栈
{
switch( ch ) //为运算符时则,弹出两个操作数,先弹出的为右操作数、后为左,并将计算结果入栈
{
case '+':
st[top-1] = st[top-1] + st[top];
break;
case '-':
st[top-1] = st[top-1] - st[top];
break;
case '*':
st[top-1] = st[top-1] * st[top];
break;
case '/':
if( st[top] != 0 )
st[top-1] = st[top-1] / st[top]; //除数不能为 0
else
{
return 0; //除0错误
}
break;
}
top--;
}
}
n = st[top]; //表达式终止时,栈中的值即为计算结果
return true;
}
//输出后缀表达式
void zh::disp_exp()
{
cout << "后缀表达式为";
cout << exp << endl;
cout << endl;
}
int main()
{
zh A;
if( A.trans() == 0 )
cout << "中缀表达式不正确" << endl;
else
{
A.disp_exp();
if( A.CompValue() == 1 )
cout << "计算结果: " << A.Get_n() << endl;
else
cout << "计算错误" << endl;
}
return 0;
}