栈的应用之中缀转后缀

栈的应用之中缀转后缀详解

先理一下大概的思路:
中缀表达式一般有操作数,运算符,括号,运算符和括号又存在运算优先级问题,这就是我们需要处理的问题。
中缀表达式转后缀表达式时:
1、遇到操作数或 ‘.’ 直接写入后缀表达式;
2、遇到左括号直接进入操作符的栈中;
3、遇到运算符时,将该运算符与3、栈顶元素比较,如果优先级高于栈顶元素,直接入栈,反之则将栈顶元素出栈,并写入后缀表达式,该运算符入栈;
4、 遇到右括号时,将栈中元素出栈并写入后缀表达式,直到遇到左括号结束,并将左括号也出栈;
5、最后将栈中元素全部出栈并写入后缀表达式。

下面来看具体步骤和代码:

一、中缀转后缀

1、定义一个运算符判断函数,如果该字符是运算符,返回1;否则返回0

int is_operation(char op){     //op是要判断的字符
	switch(op){
		case '+':
		case '-':
		case '*':
		case '/':return 1;
		default:return 0;
	}
}

2.定义一个整型函数,用来返回运算符的优先级大小(不是运算符(比如 ‘#’ )的符号优先级为-1 )

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

3.开始转化:这里定义了一个opst[]数组来作为操作符栈。
在中缀表达式的末尾加上一个 ‘#’ 来作为循环结束的条件

while(e[i] != '#'){}

在循环体内:

1)遇到数字和小数点直接写入后缀表达式

if((e[i] >= '0' && e[i] <= '9') || e[i] == '.'){
			f[j++] = e[i];  //f[]是存放后缀表达式的数组
					//e[]是存放中缀表达式的数组
		}

2)遇到左括号直接进操作符栈

else if(e[i] == '('){
			opst[top] = e[i]; top++; //opst[]是操作符栈
		}

3)遇到右括号把左括号后的操作符全部写入后缀表达式

else if(e[i] == ')'){
			t = top - 1;     //用 t 变量来表示栈顶下面的那个值(找到'(')
			while(opst[t] != '('){  //直到遇到'('才结束循环
				f[j++] = opst[--top]; //写入后缀表达式并出栈
				t = top - 1;
			} 
			top -- ;       //将'('出栈
		}

4)比较运算符优先级大小

else if(is_operation(e[i])){
			f[j++] = ' ';//用空格分开两个操作数
			while(priority(e[i]) <= priority(opst[top-1])){
				f[j++] = opst[--top];//优先级小的出栈 
			}
			opst[top] = e[i]; top++;//当前元素进栈 
		} 

5)把剩余的操作符出栈并写入后缀表达式

while(top) f[j++] = opst[--top];

此时已经把中缀表达式转成了后缀表达式,然后我们需要先把操作数从字符转为数字,再进行运算。

二、后缀表达式的计算

1.操作数字符转为浮点型数字(整数部分和小数部分)。
这里的i一定要用指针,因为要在该函数里改变i的值并使之在调用的地方有效。

double readNumber(char f[],int *i){}

1)整数部分
字符转浮点型,这里有两种方法:
第一种是直接用 f[ i ] - '0’ ,第二种是使用atof函数:atof(f[i]).
这里的x每加一次都要*10,这是因为十进制的进制是10.

while(f[*i] >= '0' && f[*i] <= '9'){   //直到这个整数全部读出了就结束(遇到其他符号)。
		x = x*10 + (f[*i] - '0');  //还原操作数
		(*i)++;  //向后寻找
	}

2)小数部分
这里与整数部分类似,就是多了个标志变量k,k每加1,说明该数的小数部分就多了一位,在最后需要除以相应的位数。

if(f[*i] == '.'){
		(*i)++;     //后移一位(移到'.'的后面一位)
		while(f[*i] >= '0' && f[*i] <= '9'){
			x = x*10 + (f[*i] - '0');
			(*i)++;
			k++;    //小数部分多一位,k+1
		}
	}
while(k!=0){     //每次循环除以10,直到k为0
		x = x/10.0;
		k -- ;  
	}

2.计算后缀表达式的值
定义两个浮点型变量x1,x2 来表示两个操作数, obst[]表示操作数栈

1)循环,直到遇到’#'结束

while(f[i] != '#'){}

2)将操作数入栈

if(f[i] >= '0' && f[i] <= '9'){
			obst[top] = readNumber(f,&i);
			top++;
		}

3)如果是空格(即后缀表达式里的操作数分隔符),就继续向下

else if(f[i] == ' ')    i++;

4)进行四则运算

else if(f[i] == '+'){
			x1 = obst[--top];
			x2 = obst[--top];
			obst[top] = x1 + x2;  //将运算结果存入操作数栈,继续进行运算
			top++; i++;
		}
		else if(f[i] == '-'){
			x1 = obst[--top];
			x2 = obst[--top];
			obst[top] = x1 - x2;
			top++; i++;
		}
		else if(f[i] == '*'){
			x1 = obst[--top];
			x2 = obst[--top];
			obst[top] = x1 * x2;
			top++; i++;
		}
		else if(f[i] == '/'){
			x1 = obst[--top];
			x2 = obst[--top];
			obst[top] = x2 / x1;
			top++; i++;
		}

5)返回操作数栈的第一个数字,即为最后的结果。

return obst[0];   //后缀表达式运算的最后结果

到这里,中缀转后缀表达式,以及后缀表达式的运算都搞定啦。
希望能帮到对中缀转后缀还是不太理解的同学。

最后在此附上程序完整代码. GitHub地址:https://github.com/jie12366/postfix.git

猜你喜欢

转载自blog.csdn.net/qq_40663357/article/details/82982802
今日推荐