C++ - 中缀表达式转后缀表达式

中缀表达式转后缀表达式遵循如下原则:ios

1.遇到操做数,直接输出;
2.栈为空时,遇到运算符,入栈;
3.遇到左括号,将其入栈;
4.遇到右括号,执行出栈操做,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出;
5.遇到其余运算符’+”-”*”/’时,弹出全部优先级大于或等于该运算符的栈顶元素,而后将该运算符入栈;
6.最终将栈中的元素依次出栈,输出。
通过上面的步骤,获得的输出既是转换获得的后缀表达式。
举例:a+b*c+(d*e+f)g ———> abc*+de*f+g*+数组

图示上述过程:

由于比较懒,而恰好在网上看到画的还不错的图,因此就直接贴过来了哦。但愿做者不要怪罪哦。。。
遇到a,直接输出:app

这里写图片描述

遇到+,此时栈为空,入栈:
这里写图片描述函数

遇到b,直接输出:
这里写图片描述
遇到*,优先级大于栈顶符号优先级,入栈:
这里写图片描述spa

遇到c,输出:
这里写图片描述
到+,目前站内的与+优先级都大于或等于它,所以将栈内的,+依次弹出而且输出,而且将遇到的这个+入栈:
这里写图片描述
遇到(,将其入栈:
这里写图片描述3d

遇到d,直接输出:
这里写图片描述
遇到*,因为的优先级高于处在栈中的(,所以入栈:
这里写图片描述
遇到e,直接输出:
这里写图片描述
遇到+,栈顶的优先级高于+,可是栈内的(低于+,将出栈输出,+入栈:这里写图片描述code

遇到f,直接输出:
这里写图片描述
遇到),弹出栈顶元素而且输出,直到弹出(才结束,在这里也就是弹出+输出,弹出(不输出:
这里写图片描述
遇到*,优先级高于栈顶+,将*入栈
这里写图片描述
遇到g,直接输出: :
这里写图片描述
此时已经没有新的字符了,依次出栈并输出操做直到栈为空:
这里写图片描述orm

二. 后缀表达式求值

从左往右扫描后缀表达式,遇到操做数入栈,遇到运算符、弹出两个操做数、计算结果并将结果入栈( 注:先弹出的为右操做数,后弹出的为左操做数),循环以上过程,知道扫描完后缀表达式,此时栈中的数即为运算结果。

/* 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;
}