逆波兰表达式

来源:互联网 发布:黑鹰坠落 知乎 编辑:程序博客网 时间:2024/04/28 19:40

  逆波兰表达式 rpn(Reverse Polish Notation)

  逆波兰表达式,它的语法规定,表达式必须以逆波兰表达式的方式给出。逆波兰表达式又叫做后缀表达式。这个知识点在数据结构和编译原理这两门课程中都有介绍,下面是一些例子:
  正常的表达式 逆波兰表达式
  a+b a,b,+
  a+(b-c) a,b,c,-,+
  a+(b-c)*d a,d,b,c,-,*,+
  a=1+3 a=1,3 +
  http=(smtp+http+telnet)/1024 写成什么呢?
  http=smtp,http,telnet,+,+,1024,/
  逆波兰表达式是一种十分有用的表达式,它将复杂表达式转换为可以依靠简单的操作得到计算结果的表达式。例如(a+b)*(c+d)转换为ab+cd+*d+
  它的优势在于只用两种简单操作,入栈和出栈就可以搞定任何普通表达式的运算。其运算方式如下:
  如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。
  将一个普通的中序表达式转换为逆波兰表达式的一般算法是:
  1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
  (2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
  (3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
  (4)如果不是数字,该字符则是运算符,此时需比较优先关系。
  做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将栈顶的运算符从栈中弹出,直到栈顶运算符的优先级低于当前运算符,将该字符入栈。
  (5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
  其中运算符优先级如下:
  */:4
  +-:3
  (:2
  ):1
 


typedef int SElemType;

typedef struct SqStack

{ char *base;

char *top;

char stacksize;

}SqStack;

程序

void InitStack (SqStack &S)

{

S.base=(char *) malloc (STACK_INIT_SIZE *sizeof(char));

if (!S.base)

exit (OVERFLOW); //为栈S分配存储空间失败

S.top=S.base;

S.stacksize=STACK_INIT_SIZE;

}

int Push(SqStack &S,char ch)

// 将元素e插入到栈S中,成为新的栈顶元素

{

if (S.top-S.base>S.stacksize) //Stack==full?

{ S.base=(char *)realloc(S.base,(S.stacksize+STACKINCREMENT *sizeof(char)));

if (!S.base)

{ printf(“Failure to reallocate the Memory units!:/n”);

exit(OVERFLOW);

}

S.top=S.base+S.stacksize; //To Modify pointer of Satck top

S.stacksize+=STACKINCREMENT; //To modify the size of stack

} // end of if

*S.top++=ch; //先将e送入栈顶指针所指向的单元,再将栈顶指针加1

return(OK);

} //end of Push() subfunction

int Pop(SqStack &S,char &ch)

{

if (S.top==S.base)

{

printf(“下溢!”);

return (ERROR);

}

ch=*--S.top;

return (OK);

}

void Translation()

{//将算术表达式转化为逆波兰表达式,num为算术表达式的字符总个数

int i,j;

char str[100],exp[100],ch;

SqStack S;

InitStack(S);

i=1;

printf(“ 请输入算术表达式字符串,求其逆波兰表达式,以#为结束标志,如a-b*c/(3+6)#:/n”);

do

{

scanf(“%c”,&str);

i++;

}while(str[i-1]!=’#’);

str[0]=’(‘; //将表达式放在()内

str[i-1]=’)’;

str=’#’;

i=0;

j=0;

while(str!=’#’)

{ if((str>=’0’ &&str<=’9’)||(str>=’a’ &&str<=’z’))

{

exp[j]=str;

j++;

} //end of if

else if(str==”(”)

Push(S.str);

else if(str==’)’)

{ while(*(S.top-1)!=’(’)

//将S中左括弧“(”以前的所有字符依次弹出并存入数组exp中

{ Pop(S,ch); exp[j]=ch; j++; }

S.top--;

} //end of elseif

else if(str==’+’||str==’-’) //如果判定为“+”号或“-”号,则做如下操作

{ while((s.top!=S.base)&&(*(S.top-1)!=’(’))

//将S中左括弧“(”以前字符依次弹出并存入数组exp 中

{ Pop(S,ch); exp[j]=ch; j++; }

Push(S,str);

} //end of else if

else if (str==’*’||str==’/’)

{

while((*(S.top-1)==’*’)||(*(S.top-1)==’/’))

{ Pop(S,ch); exp[j]=ch; j++; }

Push(S,str);

} //end of else if

i++;

} //end of while

exp[j]=’#’;

printf(“/n/n输入的算术表达式”);

i=1;

while(str[i+1]!=’#’)

{ printf(“%c”,str);

i++;

} //end of while

printf(“ 逆波兰表达式为:/n”);

i=0;

while(exp!=’#’)

{ printf(“%c”,exp); i++; }
}
void main()
{
Translation();
printf(“/n”);
printf(“…OK…!”)
getch();
}

还有一种方法,用2叉树.
原创粉丝点击