逆波兰算法(多位数运算)
来源:互联网 发布:我国的有限元软件 编辑:程序博客网 时间:2024/06/11 03:49
【问题描述】
在计算机中,算术表达式由常量、变量、运算符和括号组成。由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行。因而在程序设计时,借助栈实现。
【任务要求】
算法输入:一个算术表达式,由常量、变量、运算符和括号组成(以字符串形式输入)。为简化,规定操作数只能为正整数,操作符为+、-*、/,用#表示结束。
算法输出:表达式运算结果。
算法要点:设置运算符栈和运算数栈辅助分析算符优先关系。在读入表达式的字符序列的同时,完成运算符和运算数的识别处理,以及相应运算。
问题分析
如果此类问题只需要计算10以内的数字运算,会非常简单。这里不再赘述。然而当需要计算多位数的计算时,例如123+(23-11)*113-45/3=?,当输入为字符串时,需要将表达式中运算数分离出来,并且利用负数代替其中的运算符。
本代码,借助《数据结构(C语言版)》(严蔚敏著)书中的53页算法,及其中关于运算符优先级的表格。
//2017 1 2 wangran 赵海航//这个不能计算负数//表达式中也不要出现0#include<stdio.h>#include<malloc.h>#include<math.h>float num[100]={0};//使用-1,-2,-3,-4,-5,-6,-7,分别代表,+,-,*,/,(,),#//使用-1,0,1分别代表<,=,>int operate[8][8]={0, 0, 0, 0, 0, 0, 0, 0,//书p53表格 0, 1, 1,-1,-1,-1, 1, 1, 0, 1, 1,-1,-1,-1, 1, 1, 0, 1, 1, 1, 1,-1, 1, 1, 0, 1, 1, 1, 1,-1, 1, 1, 0,-1,-1,-1,-1,-1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0,-1,-1,-1,-1,-1, 0, 0,};struct StackNode{ float data; struct StackNode *next;};struct LinkStack{ struct StackNode *top; float length;};struct LinkStack * InitStack ()//初始化栈结构{ struct LinkStack *S; S=(struct LinkStack *)malloc(sizeof(struct LinkStack)); S->top=NULL; S->length=0; return S;}void Push(struct LinkStack * S,float e)//入栈{ struct StackNode *p; p=(struct StackNode*)malloc(sizeof(struct StackNode)); p->data=e; p->next=S->top; S->top=p; S->length++;}void Pop(struct LinkStack *S)//出栈{ struct StackNode *p; p=(struct StackNode*)malloc(sizeof(struct StackNode)); p=S->top; S->top=S->top->next; S->length--; free(p);}float GetTop(struct LinkStack *S)//获得栈顶元素{ float e; e=S->top->data; return e;}int StackEmpty(struct LinkStack *S)//判断是否为空栈{ return !(S->length);}void getnum()//将字符转化为整形数{ char c; int temp=0,temp2=0; int index=0; while((c=getchar())&&c!='\n') { if (isdigit(c))//如果是数字 { temp=temp*10+(c-'0'); } else { if (c=='+') { temp2=-1; } else if (c=='-') { temp2=-2; } else if (c=='*') { temp2=-3; } else if (c=='/') { temp2=-4; } else if (c=='(') { temp2=-5; } else if (c==')') { temp2=-6; } else if (c=='#') { temp2=-7; } } if (temp!=0&&temp2!=0)//此处我目前只想到这么写, { num[index++]=temp; num[index++]=temp2; temp=temp2=0; } else if (temp==0&&temp2!=0) { num[index++]=temp2; temp2=0; } }}int precede(float a,float b)//获取a,b的优先级{ a=(int)(fabs(a)); b=(int)(fabs(b)); int n=a; int m=b; return operate[n][m];}float OPERATE(float a,float theta,float b)//对于a,b操作{ switch((int)theta) { case -1:return a+b; case -2:return a-b; case -3:return a*b; case -4:return a/b; }}float operandTypeEvaluateExperssion ()//计算函数,此算法使用使用书中53页{ int i=0,c; float a,b,theta,x; struct LinkStack *OPTR,*OPND; OPTR=InitStack(); OPND=InitStack();//初始化 Push(OPTR,-7); c=num[i]; while(c!=-7||GetTop(OPTR)!=-7) { if (c>=0) { Push(OPND,c); c=num[++i]; } else { switch(precede(GetTop(OPTR),c)) { case -1: Push(OPTR,c); c=num[++i]; break; case 0: //Pop(OPTR,x); x=GetTop(OPTR);//这里由于不能使用引用操作,所以用gettop和pop代替书中的引用 Pop(OPTR); c=num[++i]; break; case 1: //Pop(OPTR,theta); theta=GetTop(OPTR); Pop(OPTR); // Pop(OPND,b); b=GetTop(OPND); Pop(OPND); //Pop(OPND,a); a=GetTop(OPND); Pop(OPND); Push(OPND,OPERATE(a,theta,b)); break; }//switch } }//while return GetTop(OPND);}int main(){ getnum();// int i;// for (i=0;i<20;i++)// printf("%d ",num[i]); printf("\n结果为:%f\n",operandTypeEvaluateExperssion());}
结果如图:
注:
此程序关键地方在于getnum()函数。
1 0
- 逆波兰算法(多位数运算)
- 计算器(逆波兰运算表达式)
- 逆波兰表达式运算
- 逆波兰运算
- 简易计算器(逆波兰算法)
- 逆波兰式算法
- java 逆波兰算法
- 逆波兰表达式算法
- 逆波兰表达式算法
- 逆波兰算法
- 实现逆波兰算法
- 逆波兰算法源码
- 逆波兰表达式算法
- 逆波兰计算法
- 逆波兰表达式算法
- 逆波兰表达式算法
- 逆波兰算法
- 逆波兰表达式算法
- 使用<script>来更快速的请求接口
- TortoiseGit
- 【网络流24题】餐巾计划问题
- redis学习三,Redis主从复制和哨兵模式
- 解释器模式
- 逆波兰算法(多位数运算)
- (2)构建工具之maven与MyEclipse整合
- Bible读经体会
- 一些想法
- SharedPreferences中getBoolean()
- 【oracle】oracle建立全文检索
- pb文件的使用
- leetcode 94 Binary Tree Inorder Traversal C++
- Windows下Nginx的启动、停止等命令