/* 中缀转前缀参考算法: 1)求输入串的逆序。(中缀转前缀是从右向左访问表达式) 2)检查输入的下一元素。 3)假如是操作数,把它添加到输出串中。 4)假如是闭括号,将它压栈。 5)假如是运算符, i)假如栈空,此运算符入栈。 ii)假如栈顶是闭括号,此运算符入栈。 iii)假如它的优先级高于或等于栈顶运算符,此运算符入栈。 iv)否则,栈顶运算符出栈并添加到输出串中,重复步骤5。 6)假如是开括号,栈中运算符逐个出栈并输出,直到遇到闭括号。闭括号出栈并丢弃。 7)假如输入还未完毕,跳转到步骤2。 8)假如输入完毕,栈中剩余的所有操作符出栈并加到输出串中。 9)求输出串的逆序。 */
/* 中缀转后缀参考算法: 1)求输入串的正序。(中缀转后缀是从左向右访问表达式) 2)检查输入的下一元素。 3)假如是操作数,把它添加到输出串中。 4)假如是开括号,将它压栈。 5)假如是运算符, i)假如栈空,此运算符入栈。 ii)假如栈顶是开括号,此运算符入栈。 iii)假如它的优先级高于或等于栈顶运算符,此运算符入栈。 iv)否则,栈顶运算符出栈并添加到输出串中,重复步骤5。 6)假如是闭括号,栈中运算符逐个出栈并输出,直到遇到开括号。开括号出栈并丢弃。 7)假如输入还未完毕,跳转到步骤2。 8)假如输入完毕,栈中剩余的所有操作符出栈并加到输出串中。 9)求输出串的正序。 */
/************************
author's email:wardseptember@gmail.com
date:2018.1.5
利用顺序栈将中缀式转换成前、后缀式并求值
************************/
#include <iostream>
#include<string>
using namespace std;
#define maxSize 50
//siffix后缀式 prefix前缀式 infix中缀式
int priority(char op);//判断运算符级别函数;其中* /的级别为2,+ -的级别为1;
bool isOperatorDigit(char op);//判断输入串中的字符是不是操作符,如果是返回true
int op(int a, char Op, int b);//本函数是运算函数,用来完成算式“a Op b”的运算
string infixConvertPrefix(string s);//将一个中缀串转换为前缀串
int calculatePrefix(string s);//计算前缀式的值
string infixConvertSiffix(string s);//将一个中缀串转换为后缀串
int calculateSiffix(string s);//后缀式计算函数
void main() {
//测试表达式为(((((4+2)/3)*5)-4)/2)*7,其前缀式为* / - * / + 4 2 3 5 4 2 7 ,其后缀式为4 2 + 3 / 5 * 4 - 2 / 7 * ,其值为21。
string input, output;
cout << "请输入前缀表达式(表达式中的数字只能是个位数):";
cin >> input;
output = infixConvertPrefix(input);
cout << "前缀串为:";
for (int i = output.length() - 1; i >= 0; i--)//9)求输出串的逆序。
cout << output[i]<<' ';
cout << endl;
cout << "前缀式的计算结果为:";
cout << calculatePrefix(output) << endl;
//string input, output;
//cout << "请输入前缀表达式(表达式中的数字只能是个位数):";
//cin >> input;
//output = infixConvertSiffix(input);
//cout << "后缀串为:";
//for (int i = 0; i <= output.length() - 1; i++)//9)求输出串的逆序。
// cout << output[i]<<' ';
//cout << endl;
//cout << "后缀式的计算结果为:";
//cout << calculateSiffix(output) << endl;
system("pause");
}
int priority(char op)//判断运算符级别函数;其中* /的级别为2,+ -的级别为1;
{
int level;
switch (op)
{
case'+':
case'-':level = 1; break;
case'*':
case'/':level = 2; break;
default:level = 0; break;
}
return level;
}
bool isOperatorDigit(char op)//判断输入串中的字符是不是操作符,如果是返回true
{
if (op == '+' || op == '-' || op == '*' || op == '/')
return true;
else
return false;
}
int op(int a, char Op, int b) {//本函数是运算函数,用来完成算式“a Op b”的运算
if (Op == '+')return a + b;
if (Op == '-')return a - b;
if (Op == '*')return a*b;
if (Op == '/')
{
if (b == 0)//分母为0的情况
{
cout << "Error" << endl;
return 0;
}
else
return a / b;
}
}
string infixConvertPrefix(string s)//将一个中缀串转换为前缀串,
{
char stack[maxSize];//定义顺序栈
int top = -1;//栈顶指针,为-1表示栈为空;
string output = "";//输出串
for (int i = s.length() - 1; i >= 0;)//1)求输入串的逆序。
{
if (s[i] >= 48 && s[i] <= 57)
output = output + s[i];//3)假如是操作数,把它添加到输出串中。
if (s[i] == ')')//4)假如是闭括号,将它压栈。
{
top++;
stack[top] = s[i];
}
while (isOperatorDigit(s[i]))//如果是运算符,执行算法(5)对应操作;
{
if (top == -1 || stack[top] == ')' || priority(s[i]) >= priority(stack[top]))
{
top++;
stack[top] = s[i];
break;
}
else
{
output = output + stack[top];
top--;
}
}
if (s[i] == '(')//6)假如是开括号,栈中运算符逐个出栈并输出,直到遇到闭括号。闭括号出栈并丢弃。
{
while (stack[top] != ')')
{
output = output + stack[top];
top--;
}
top--;//闭括号出栈并丢弃
}
i--;//7)假如输入还未完毕,跳转到步骤2。
}
while (top != -1)//8)假如输入完毕,栈中剩余的所有操作符出栈并加到输出串中。
{
output = output + stack[top];
top--;
}
return output;
}
int calculatePrefix(string s) {//计算前缀式的值
int i, a, b, c;//a、b为操作数,c用来保存结果
/*定义顺序栈,注意元素必须为int型,不能死char型。虽然要求输入的中缀表达式
里面的数字都是个位数,但是运算过程中可能产生多位的数字,所以要用int型*/
int stack[maxSize];
int top = -1;//栈顶指针,为-1表示栈为空;
char Op;
for (i = 0; i <= s.length() - 1; ++i)//注意此时前缀式的逆序
{
if (s[i] >= 48 && s[i] <= 57)//假如是操作数,把它添加到输出串中。
stack[++top] = s[i] - '0';//将字符型转化为整型并入栈
else //如果遇到运算符,则开始运算
{
Op = s[i]; //取运算符
a = stack[top--];//取第一个操作数
b = stack[top--];//取第二个操作数
c = op(a, Op, b);//运算
stack[++top] = c;//运算结果入栈
}
}
return stack[top];//返回最终运算结果
}
string infixConvertSiffix(string s)
{
char stack[maxSize];//定义顺序栈
int top = -1;//栈顶指针,为-1表示栈为空;
string output = "";//输出串
for (int i = 0; i <= s.length() - 1;)//1)求输入串的正序。
{
if (s[i] >= 48 && s[i] <= 57)
output = output + s[i];//3)假如是操作数,把它添加到输出串中。
if (s[i] == '(')//4)假如是开括号,将它压栈。
{
top++;
stack[top] = s[i];
}
while (isOperatorDigit(s[i]))//如果是运算符,执行算法(5)对应操作;
{
if (top == -1 || stack[top] == '(' || priority(s[i]) >= priority(stack[top]))
{
top++;
stack[top] = s[i];
break;
}
else
{
output = output + stack[top];
top--;
}
}
if (s[i] == ')')//6)假如是闭括号,栈中运算符逐个出栈并输出,直到遇到开括号。开括号出栈并丢弃。
{
while (stack[top] != '(')
{
output = output + stack[top];
top--;
}
top--;//开括号出栈并丢弃
}
i++;//7)假如输入还未完毕,跳转到步骤2。
}
while (top != -1)//8)假如输入完毕,栈中剩余的所有操作符出栈并加到输出串中。
{
output = output + stack[top];
top--;
}
return output;
}
int calculateSiffix(string s) {//后缀式计算函数
int i, a, b, c;//a、b为操作数,c用来保存结果
/*定义顺序栈,注意元素必须为int型,不能死char型。虽然要求输入的中缀
表达式里面的数字都是个位数,但是运算过程中可能产生多位的数字,所以
要用int型*/
int stack[maxSize];
int top = -1;//栈顶指针,为-1表示栈为空;
char Op;
for (i = 0; i <= s.length() - 1; ++i)
{
if (s[i] >= 48 && s[i] <= 57)//假如是操作数,把它添加到输出串中。
stack[++top] = s[i] - '0';//将字符型转化为整型并入栈
else //如果遇到运算符,则开始运算
{
Op = s[i]; //取运算符
//注意这是这里是和计算前缀式的值的区别
b = stack[top--];//取第二个操作数
a = stack[top--];//取第一个操作数
c = op(a, Op, b);//运算
stack[++top] = c;//运算结果入栈
}
}
return stack[top];//返回最终运算结果
}