逆波兰表达式

逆波兰表达式

恶补下算法,常用在计算器 , 或者编译原理中的表达式 。

原理

在原理介绍和相关知识扩展推荐一篇博客 。

分析算法

给出一个表达式算出正确结果 ,例如 (1+2*(3+4)) , 转为逆波兰表达式1+2*+34 , 我们使用两个栈来辅助运算 , 一个操作数栈(nstack)和一个操作符栈(ostack) , 在上述表达式,从左到右读取数据 , 首先在算术表达式只有三种操作符 , +/- , * / / , (), 优先级从左到右递增 , 所以当遇到第二级优先级时我们就可以在准备运算 , 如果操作符右边的符号不是括号 ,则真正的开始运算 , 例如上述1+2*(3+4) , 当1 ,‘ + ’ , 2 分别入栈以后 , 入栈 “” , 但是由于接下来入栈“(” , 所以我们不计算乘法 ,而去计算括号内的运算 , 假如算式为1+23 + 4的话, 此时则开始运算 将2 , “ * ” 出栈 , 计算结果为6 再入栈。

算法实现, 我原本打算使用C语言来解决这个问题 , 但是C语言没有自己的栈库函数,(这里反应出自己的代码整合能力自己写过什么都没有整理出来,还需进步) , 所以使用C++来实现算法。

#include 
#include 
using namespace std;

int getnums(char * str,int * num){
	int count = 0 ; 
	int n = * num ;
	char temp;
	char nstr[20]={0};
	while(1)
	{
		temp = str[n];
		if (temp == ' ' ) {
			n++;
			continue;
		}
		if(temp <= '9' && temp >= '0'){
			nstr[count]=temp;
			count++;
			n++;
		}
		else
			break;
	}
	*num=n;
	return atoi(nstr);
}


int main(void){
	int p = 0 ;
	char str[1000]={0};
	stack  nstack;
	stack  ostack;
	gets(str);
	ostack.push(str[p++]);
	for (  ;p < strlen(str)  ;){
		 
		 nstack.push(getnums(str , &p));

label1:
		 while(str[p] == ' ')
			 p++;
		 switch(str[p]){
			case '-':
				ostack.push('-');
				p++;
				break;
			case '+':
				ostack.push('+');
				p++;
				break;
			case '*':
				ostack.push('*');
				p++;
				if(str[p] != '('){
					int A = getnums(str,&p);
					int B = nstack.top();
					nstack.pop();
					nstack.push(A*B); 
					ostack.pop();
				}
				goto label1;
				break;
			case '//':
				ostack.push('//');
				p++;
				if(str[p] != '('){
					int A = getnums(str,&p);
					int B = nstack.top();
					nstack.pop();
					nstack.push(A/B); 
					ostack.pop();
				}
				break;
			case '(':
				ostack.push('(');
				p++;
				break;
			case ')':      
				while(ostack.top() != '('){
					int A = nstack.top();
					nstack.pop();
					int B = nstack.top();
					nstack.pop();
					switch ( ostack.top()){
						case '+' : nstack.push(A+B);
							break;
						case '-' : nstack.push(A-B);
							break;
						case '*' : nstack.push(A*B);
							break;
					}
					ostack.pop();
				}
				ostack.pop();
				if(ostack.empty()){
					p++;
					break;
				}
					
				if(ostack.top() == '*'){
					int A = nstack.top();
					nstack.pop();
					int B = nstack.top();
					nstack.pop();
					nstack.push(A*B);
					ostack.pop();
				}
				else if(ostack.top() == '//'){
					int A = nstack.top();
					nstack.pop();
					int B = nstack.top();
					nstack.pop();
					nstack.push(A/B);
					ostack.pop();
				}
				p++;
				goto label1;
				break;
			default:
				break;
		 }
	}
	printf("%d",nstack.top());
	return 0;
}

代码实现过程中, 其实相比于思路需要考虑更多东西 , 为了将更多细节放在算法上 ,规定数据中间没有开头 , 且为左括号开头 , 因为算法的单次操作是以右括号为目标的 , 如果最左边的没有左括号 , 那么操作次数就不够 。 其中可能还有很多问题 ,希望留言告知。

你可能感兴趣的:(娱乐编程)