码迷,mamicode.com
首页 > 其他好文 > 详细

逆波兰

时间:2014-09-09 11:40:58      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:style   os   io   使用   ar   for   sp   on   c   

 

 

一个表达式E逆波兰形式可以如下定义:

 

1)如果E是一个变量或常量,则E的后缀式是E本身。

2)如果EE1 op E2形式的表达式,这里op是如何二元操作符,则E的后缀式为E1‘E2‘ op,这里E1‘E2‘分别为E1E2的后缀式。

3)如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式。(括号直接剔除)

如:我们平时写a+b,这是中缀表达式,写成后缀表达式就是:ab+

(a+b)*c-(a+b)/e的后缀表达式为:

(a+b)*c-(a+b)/e

((a+b)*c)((a+b)/e)-

((a+b)c*)((a+b)e/)-

(ab+c*)(ab+e/)-

ab+c*ab+e/-

 

1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入S2

2)若取出的字符是运算符,则将该运算符与S1栈栈顶元素比较,如果该运算符优先级大于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,则将该运算符送入S1栈。

3)若取出的字符是“(”,则直接送入S1栈栈顶。

4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个出栈,依次送入S2栈,此时抛弃“(”。

5)重复上面的1~4步,直至处理完所有的输入字符

6)若取出的字符是“#”,则将S1栈内所有运算符(不包括“#”),逐个出栈,依次送入S2栈。

 

逆波兰的机器运算

下面以(a+b)*c为例子进行说明:

(a+b)*c的逆波兰式为ab+c*,假设计算机把ab+c*按从左到右的顺序压入栈中,并且按照遇到运算符就把栈顶两个元素出栈,执行运算,得到的结果再入栈的原则来进行处理,那么ab+c*的执行结果如下:

1a入栈(0位置)

2b入栈(1位置)

3)遇到运算符“+”,将ab出栈,执行a+b的操作,得到结果d=a+b,再将d入栈(0位置)

4c入栈(1位置)

5)遇到运算符“*”,将dc出栈,执行d*c的操作,得到结果e,再将e入栈(0位置)

经过以上运算,计算机就可以得到(a+b)*c的运算结果e了。

 

 

#include"iostream.h" 

#include<stdlib.h> 

#include<stdio.h> 

#include<math.h> 

#define max 100 

 

char ex[max]; /*存储后缀表达式,不需要用另一个栈,直接用数组。这样也方便机器读*/ 

void trans()

{ /*将算术表达式转化为后缀表达式*/ 

char str[max]; /*存储原算术表达式*/ 

char stack[max]; /*作为栈使用*/ 

char ch; 

int sum,i,j,t,top=0; 

printf("*****************************************\n"); 

printf("*输入一个求值的表达式,以#结束。*\n"); 

printf("******************************************\n"); 

printf("算数表达式:"); 

i=0; /*获取用户输入的表达式*/ 

do

{

i++; 

cin>>str[i];

}while(str[i]!=‘#‘ && i!=max); 

sum=i; 

t=1;i=1; 

ch=str[i];i++; 

// 

while(ch!=‘#‘){ 

switch(ch)

case ‘(‘: /*判定为左括号*/ 

top++;stack[top]=ch; //stack1开始

break; 

case ‘)‘: /*判定为右括号*/ 

while(stack[top]!=‘(‘)

{ //把()之间的全部放到目标数组里面

ex[t]=stack[top];top--;t++; 

top--; //除去(符号

break; 

case ‘+‘: /*判定为加减号*/ 

case ‘-‘: 

//(看做优先级最低,加减运算之比“(”优先级高。只有出现比它低的情况它才压入进去(或者运算栈为空),否则把栈内的都放到目标数组

while(top!=0&&stack[top]!=‘(‘)

ex[t]=stack[top];top--;t++; 

top++;stack[top]=ch; 

break; 

case ‘*‘: /*判定为乘除号*/ 

case ‘/‘: 

//遇到和自己相同运算级的仍然需要把栈送入目标中。对于乘法除法,(,加减肯定比自己优先级小

while(stack[top]==‘*‘||stack[top]==‘/‘)

ex[t]=stack[top];top--;t++; 

top++;stack[top]=ch; 

break; 

case ‘ ‘:break; 

default:

while(ch>=‘0‘&&ch<=‘9‘)

{ /*判定为数字*/ 

ex[t]=ch;t++; 

ch=str[i];i++; 

i--; 

ex[t]=‘ ‘;t++; 

//这里每个数字之间存在一个空格,这样保证被分解的时候,不至于把两个数当做一个数

ch=str[i];i++; 

while(top!=0)

ex[t]=stack[top];t++;top--; 

ex[t]=‘ ‘; 

printf("\n\t原来表达式:"); 

for(j=1;j<sum;j++) 

printf("%c",str[j]); 

printf("\n\t逆波兰式:",ex); 

for(j=1;j<t;j++) 

printf("%c",ex[j]); 

 

 

void compvalue(){ /*计算后缀表达式的值*/ 

float stack[max],d; /*作为栈使用*/ 

char ch; 

int t=1,top=0; /*tex下标,topstack下标*/ 

ch=ex[t];t++; 

while(ch!=‘ ‘){ 

switch(ch){ 

case ‘+‘: 

stack[top-1]=stack[top-1]+stack[top]; 

top--; 

break; 

case ‘-‘: 

stack[top-1]=stack[top-1]-stack[top]; 

top--; 

break; 

case ‘*‘: 

stack[top-1]=stack[top-1]*stack[top]; 

top--; 

break;

case ‘/‘: 

if(stack[top]!=0) stack[top-1]=stack[top-1]/stack[top]; 

else{ 

printf("\n\t除零错误!\n"); 

exit(0); /*异常退出*/ 

top--; 

break; 

default: 

d=0; 

while(ch>=‘0‘&&ch<=‘9‘){ 

d=10*d+ch-‘0‘; /*将数字字符转化为对应的数值*/ 

ch=ex[t];t++; 

top++; 

stack[top]=d; 

ch=ex[t];t++; 

printf("\n\t计算结果:%g\n",stack[top]); 

}

 

void main(){ 

trans(); 

compvalue(); 

}

逆波兰

标签:style   os   io   使用   ar   for   sp   on   c   

原文地址:http://www.cnblogs.com/notlate/p/3961778.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!