顺序栈应用2(利用顺序栈将中缀式转换成前、后缀式并求值)

 
 
/*
中缀转前缀参考算法:
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:[email protected]
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];//返回最终运算结果
}
以上如有错误,请指出,大家共同学习进步

猜你喜欢

转载自blog.csdn.net/wardseptember/article/details/78985302
今日推荐