中缀表达式转后缀表达式(计算结果)

我们平常使用的式子都是中缀表达式。

在程序中,我们可以利用栈,将中缀表达式转换为后缀表达式。也利用栈,将后缀表达式计算出结果。

①中缀表达式转后缀表达式

如1+2*3/(3-1)  --->  1 2 3 * 3 1 - / +

转换的思想:

一个空的后缀表达式

一个存放符号的栈s

在转换的过程中,需要加入空格以区分不同数字与数字,数字与符号。(具体代码中体现)

 

字符具体操作
数字直接输出至后缀式中
字符 '('将 '(' 放入符号栈s当中
字符 ')'将栈s中直到第一个 '(' 的前的符号都输出到后缀表达式中,并且
运算符:栈外优先级 > 栈内优先级此运算符直接入栈
运算符:栈外优先级 <= 栈内优先级将栈顶符号出栈输出到后缀式中,此运算符入栈

最后把栈内剩余的符号输出至后缀表示式

操作符优先级

 

#0
(1
)6
+  -2          
*  /3

 

例子:2+3*(4-2) 式子共9个运算符

 

2是数字,直接放到后缀表达式:    2 (后缀表达式)   | #(栈)

+是符号,'+' > '#' ,直接入栈:      2          | # +
3是数字,直接放到后缀表达式:    2 3       | # +

*是符号,'*' > '+' ,直接入栈:        2 3       | # + *

(是符号,'(' , 直接入栈:                 2 3      | # + * (
4是数字,直接放到后缀表达式:    2 3 4      | # + * (

-是符号,'-'  >  '(' , 直接入栈:       2 3  4    | # + * ( -

 

2是数字,直接放到后缀表达式:    2 3 4  2    | # + * (

)是符号,直接将(后的输出    :       2 3  4 2 -  | # + * 

 

最后,将栈内除了#的所有符号输出到后缀中。2 3 4 2 - * +

②计算后缀表达式的结果

将后缀表达式一一入栈

入栈是数字时,直接放进去

入栈是符号时,将栈顶的两个数拿出来进行计算(注意是被减数还是减数,被除数还是除数),并将结果放回至栈顶

最后遍历完,将栈内剩下的唯一结果输出。

#include <iostream>
#include <stack>
#include <math.h>
using namespace std;

bool Number(char ch)
{
	if(ch>=48 && ch<=57)
	    return true;
	else
	    return false;
}

void Input(char*& str){     //输入表达式,并且检测是否正确 
	cout<< "请输入想要转换的表达式" <<endl;
	while(1){
		cin >> str;
		if(Number(str[0]))
		{
			break;
		}
		else
		{
			cout<<"输入的表达式格式有误,请重新输入"<<endl;
			delete[] str;
		}
	} 
}

void AddSpace(char*& arr)
{
	*arr = ' ';
	arr++;
}



int GetPriority(char a)
{
	switch(a)
	{
	    case '#':
		    return 0;
		case '(':
			return 1;
		case '+':
		    return 2; 
		case '-':
		    return 2; 
		case '*':
			return 3;
		case '/':
		    return 3;
		default:
			return -1;
	}
}


char* GetRevSequence(){ //将input表达式转为后缀表达式 
	char* str_ori = new char[30];
	char* str_res = new char[30];
	char* str_record;
	stack<char> s;
	s.push('#');
	Input(str_ori);
	str_record = str_res;
	while(*str_ori)
	{
		cout<<*str_ori<<endl;
		if(Number(*str_ori)) //如果str_ori是数字,直接放到后缀序列里 
		{ 
			*str_res = *str_ori;
			*str_res++;
			*str_ori++;
		}
		else//如果是操作符 
		{
			if(Number(*(str_ori-1)))//如果前一位是数字的话,就加空格,来分隔数字 
			{
				AddSpace(str_res);
			}
			if(*str_ori=='(')  //如果是'(',直接入栈 
			{
				s.push(*str_ori);
				str_ori++;
			}
			else if(*str_ori==')')//如果是')',则将栈中第一个'('前的都输出,并且将)出栈
			{ 
			    while(s.top()!='(')
				{
					*str_res=s.top();
					s.pop();
				//	str_ori++;
					str_res++;
					AddSpace(str_res);
				}
				str_ori++; //注意这里是在循环外,str_ori加一 
				s.pop(); 
			}
			else if(GetPriority(*str_ori) <= GetPriority(s.top()))   //栈外小于等于栈内,把栈内输出后,把栈外放入栈内 
			{
				*str_res = s.top();
				s.pop();
				s.push(*str_ori);
				str_res++;
				str_ori++;
				AddSpace(str_res);//这里是要加个空格的,每次加数字不用加空格,但是如果判断是符号,则加了一个空格,
				                   //然后如果这个符号要在这里输出,就要在后面同样再接上一个空格,因为此符号后面只可能接数字和(
								   //如果是'('的话,绕过所有'('后,还是只会接数字,所以最终,符号出栈后面必然是数字,所以需要加空格 
			} 
			else if(GetPriority(*str_ori) > GetPriority(s.top()))   //栈外大于栈内,则直接入栈 
			{
				s.push(*str_ori);
				str_ori++;
			}
		}
	} 
	while(s.top()!='#')//将栈中所有除#符号输出
	{
		//最后遍历,只可能是以  '数字+)'  或 数字 结尾(本质都是数字结尾),所以剩余的符号在加入时需提前加入空格
		AddSpace(str_res); 
		*str_res = s.top();
		cout<<s.top()<<endl;
		s.pop();
		str_res++;
	} 
	*str_res='\0';
	
	cout<<"中缀表达式是: "<<str_record<<endl; 
	return str_record; 
}

double GetNumber(char*& arr)  //从字符串中提取出单个数字 
{
	int n=0;//用来记录此数的位数 ————————————那么带小数点的怎么弄?
	double sum[20];
	double result = 0; 
	while(Number(*arr))
	{
		sum[n] = *arr - 48;
		n++;
		arr++;
	}
	int k = n-1;
	for(int i=0;i<n;i++,k--)
	{
		result += sum[i] * pow(10,k);
	}
	return result;
}

double cal(double a, double b, char c)   //注意被减数和减数? 
{
	switch(c)
	{
		case '+': cout<<b<<c<<a<<endl; return (b + a);
		case '-':cout<<b<<c<<a<<endl;  return (b - a);
		case '*': cout<<b<<c<<a<<endl; return (b * a);
		case '/': cout<<b<<c<<a<<endl; return (b / a);
	}
	cout<<b<<c<<a<<endl; 
}


double GetResult(char* str) //从中缀转后缀 
{
	stack<double> s;
    while(*str)
    {
    	if(Number(*str))//如果是数字的话,要将空格间的多位数字提出来 
    	{
    		s.push(GetNumber(str));
		}
		else if(*str==' ')
		{
			str++;
		}
		else
		{
			double a = s.top();//右操作数 
			s.pop();
			double b = s.top();//左操作数 
			s.pop();
			s.push(cal(a,b,*str));//把新的结果放进栈里
			str++; 
		}
	}
	//cout<<s.top()<<endl;
	return s.top();
}





int main(){
//	cout << "The Result Is: "<<GetRevSequence()  <<endl;
    cout << "The Result Is: "<<GetResult(GetRevSequence())  <<endl;
	 //
}

 

 

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值