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

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

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

  • 10
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值