数据结构与算法  计算表达式(一)

一、简单说明

计算中缀表达式。比如1+2*3、(56-20-6)/(4+2-1)。

二、实现主要思路

1、为各运算符指定优先级

说明:‘=’是为了辅助比较运算符,这样子设置优先级,只有括号情况下才会有优先级相等的情况。

2、逐个扫描算数表达式,运算数用一个栈(num)存储、运算符用一个栈(op)存储

3、当右运算符优先级低于左运算符时,op栈弹出一个运算符,num栈弹出两个运算数,然后进行计算。

4、扫描表达式结束,继续扫描执行先压栈而没有执行的运算符

5、最后num栈的第一个元素就是表达式的结果。

举例说明:表达式 (56-20)/(4+2)

三、效果

四、源码

exp.c源文件

#include <stdio.h>
#include <stdlib.h> //memset()函数所在的头文件
#define SIZE 100   //定义临时存放数据的空间大小 struct  OP //运算符结构体  (这个结构体其实是一个栈的结构)
{char data[SIZE];         //存放运算符 int top;                 //相当于栈顶指针
}op;                         //定义结构体变量,op存放运算符 struct   NUM//运算数结构体  (这个结构体其实是一个栈的结构)
{float data[SIZE];         //存放运算数 int top;                 //相当于栈顶指针
}num;                        //定义结构体变量,num存放运算数struct    PRI     //用来存储运算符的优先级
{char op;   //运算符 int pri;  //优先级
};//定义左运算符优先级结构体数组
struct PRI lpri[] = {{'=',0},{'(',1},{'+',3},{'-',3},{'*',5},{'/',5},{')',6}};//定义右运算符优先级结构体数组
struct PRI rpri[] = {{'=',0},{'(',6},{'+',2},{'-',2},{'*',4},{'/',4},{')',1}}; //函数声明部分
int LeftPri(char op);//求左运算符op的优先级
int RightPri(char op);//求右运算符op的优先级
int IsOp(char ch);//判断ch是否是运算符
int JudgePri(char lop,char rop); //判断左右运算符的优先级
float CountExp(char* exp);//计算表达式
float Str2Float(char* str); //字符串转换为 float数字
void Count(char op);//*/+-运算 int main(int argc,char* argv[])
{char exp1[] = "(56-20-6)/(4+2-1)" ;char exp2[] = "5-1*2*3+12/2/2"; float res = CountExp(exp1);printf("(56-20-6)/(4+2-1)的结果是:%lf\n",res);res = CountExp(exp2);printf("5-1*2*3+12/2/2的结果是:%lf\n",res);return 0;
}int LeftPri(char op)//求左运算符op的优先级
{int i = 0;//计数器for(i = 0;i < sizeof(lpri)/sizeof(lpri[0]);i++)//求左运算符的个数sizeof(lpri)/siozeof(lpri[0]) {if(lpri[i].op == op)//如果 左运算符结构体有匹配的运算符 {return lpri[i].pri;//返回对应的运算符的优先级 } } return -1;//没有匹配的运算符
} int RightPri(char op)//求右运算符op的优先级
{int i = 0;//计数器for(i = 0;i < sizeof(rpri)/sizeof(rpri[0]);i++)//求右运算符的个数sizeof(lpri)/siozeof(lpri[0]) {if(rpri[i].op == op)//如果 右运算符结构体有匹配的运算符 {return rpri[i].pri;//返回对应的运算符的优先级 } } return -1;//没有匹配的运算符
}int IsOp(char ch)//判断ch是否是运算符
{//如果是指定的运算符则返回1,否则返回0 if(ch == '*' || ch == '/' || ch == '+' || ch == '-' || ch == '(' || ch == ')' ){return 1;}else{return 0;}
}int JudgePri(char lop,char rop)//判断左右运算符的优先级  左运算符大于右运算符返回1,相等返回0,左小于右返回-1
{if(LeftPri(lop)> RightPri(rop))//左运算符大于右运算符返回1{return 1;} else if(LeftPri(lop)== RightPri(rop))//相等返回0,只有左右括号这一种情况 {return 0;}else   //左运算符小于右运算符返回-1{return -1;}
}float CountExp(char* exp) //计算表表达式
{memset(&(num.data),0,SIZE);  //将num结构体中的数组data清零 memset(&(op.data),0,SIZE);   //将op结构体中的数组data清零num.top = -1;                //初始化栈顶指针     op.top= -1;    op.data[++op.top] = '=';  //将'='进栈 ,先++int i = 0; //用来指示str位置 char str[10] = {0};//临时存放字符串数字 while(*exp!='\0')    //循环扫描exp表达式 {if(!IsOp(*exp))   //如果不是运算符 {i = 0;memset(str,0,10);//每循环一次次清零 while(*exp>='0' && *exp<='9')//是数字 {str[i++] = *exp++ ;//将数字字符添加到str中,添加后i加1 }str[i++] = '#';//人为加上结束符 ,辅助进行字符串转换为 float数字 num.data[++num.top] =  Str2Float(str);//将字符串转换为 float数字并赋值给 num的data数组,注意top先++; }else  //是运算符 {switch(JudgePri(op.data[op.top],*exp)){case -1://栈顶的运算符优先级低,进栈 op.data[++op.top] = *exp; break;case 0://优先级一样,说明是括号 ,只有这一种情况op.top--;//将'('退栈break;case 1://栈顶的运算符优先级高,先出栈进行计算,后入栈do{Count(op.data[op.top--]);//*/+- 运算 }while(JudgePri(op.data[op.top],*exp) == 1);//直到栈顶的运算符优先级不比 右运算符的优先级高,才准备将右运算符入栈 if(*exp != ')')//如果不是')'才入栈 {op.data[++op.top] = *exp; }break;default:break;} exp++;//继续向下扫描exp } }for(i = op.top;i>0;i--)//因为上面是按根据表达式执行的,扫描执行先压栈而没有执行的{Count(op.data[i]);}return num.data[0];  //执行完毕,num.data的第一个元素就是结果
}float Str2Float(char* str) //字符串转换为 float数字
{float flt = 0.0;while(*str >= '0' && *str <= '9')//是数字 {flt =  10*flt+*str++-'0'; }//*str-'0'解释,比如当str="520",*str是字符'5'时,字符'5'的ASCII码 是 53,//而字符'0' 的ASCII码是48,那么 *str-'0' 的值是5,完成字符数字到数字的转换 // 10*解释: 比如当str="520",//第一次时flt = 10*0.0+'5'-'0' ==>是5 //第二次时flt = 10*5.0+'2'-'0' ==>是52//第三次时flt = 10*5.0+'2'-'0' ==>是520 完成字符串数字到数字的转换return flt;
}void Count(char op)//*/+-运算
{float temp = 0.0; //用来存放临时计算结果; switch(op){case '*':temp = num.data[num.top--];//取出两个数相乘 temp *= num.data[num.top--];num.data[++num.top] = temp;//将计算结果进栈 break;case '/':temp = num.data[num.top--];//取出被除数 注意是倒着取的 if(temp==0) //被除数不能为0 {printf("\n被除数为0\n");return; }temp =  num.data[num.top--]/temp; //取出除数         1 ÷2   1是除数,2是被除数 num.data[++num.top] = temp;//将计算结果进栈 break;case '+':temp = num.data[num.top--];//取出两个数相加 ,顺序不影响相加temp += num.data[num.top--]; num.data[++num.top] = temp;//将计算结果进栈 break;case '-':temp = (num.data[num.top--]);//取出被减数 ,注意是倒着取的                                    temp = (num.data[num.top--])-temp;num.data[++num.top] = temp;//将计算结果进栈 break;default:break;}
}

五、注意

有待进一步测试。

数据结构与算法 计算表达式(一)相关推荐

  1. 数据结构与算法——中缀表达式转后缀表达式

    目录 什么是后缀表达式 后缀表达式示例图 栈实现后缀表达式 代码实现中缀表达式--后缀表达式 后缀表达式计算器的定义 ​​​​​​​ 什么是后缀表达式 也叫逆波兰表达式,将运算符写在操作数之后 中缀形 ...

  2. python【数据结构与算法】表达式(前缀中缀后缀表达式)与Two fork tree

    文章目录 1 相关概念 2 与二叉树关系 3 表达式转换 4 另一种方法 1 相关概念 前缀表达式(Prefix Notation)是指将运算符写在前面操作数写在后面的不包含括号的表达式,而且为了纪念 ...

  3. Java数据结构和算法(六)——前缀、中缀、后缀表达式

    前面我们介绍了三种数据结构,第一种数组主要用作数据存储,但是后面的两种栈和队列我们说主要作为程序功能实现的辅助工具,其中在介绍栈时我们知道栈可以用来做单词逆序,匹配关键字符等等,那它还有别的什么功能吗 ...

  4. python 表达式求值数据结构_python 数据结构与算法

    python 数据结构与算法 1 python常见数据结构性能 1.1 List 1.1.1 安索引取值和赋值 1.1.2 列表append和__add__() 1.1.3 使用timeit模块测试执 ...

  5. python数据结构和算法 时间复杂度分析 乱序单词检测 线性数据结构 栈stack 字符匹配 表达式求值 queue队列 链表 递归 动态规划 排序和搜索 树 图

    python数据结构和算法 参考 本文github 计算机科学是解决问题的研究.计算机科学使用抽象作为表示过程和数据的工具.抽象的数据类型允许程序员通过隐藏数据的细节来管理问题领域的复杂性.Pytho ...

  6. 【数据结构与算法篇】什么是后缀表达式?

    什么是后缀.前缀.以及中缀表达式呢?他与我们平时在数学中见到的表达式有什么区别?第一次看这个名词,我还是有点蒙,难理解,所以做以下笔记,以便日后复习,也希望可以帮助读者,以相互促进. 文章目录 前言: ...

  7. 【数据结构与算法】【12】前缀表达式、中缀表达式、后缀表达式

    什么是前缀表达式.中缀表达式.后缀表达式 前缀表达式.中缀表达式.后缀表达式,是通过树来存储和计算表达式的三种不同方式 以如下公式为例 (a+(b−c))∗d( a+(b-c) )*d(a+(b−c) ...

  8. 时间复杂度计算超全整理!!(数据结构和算法的第一步

    目录 1. 什么是数据结构? 1.1 数据结构和数据库的区别 1.1.1磁盘的特点: 2.什么是算法? 3.算法效率 3.1 如何衡量一个算法的好坏 4.时间复杂度 4.1 时间复杂度的概念 4.2 ...

  9. javascript数据结构与算法---检索算法(二分查找法、计算重复次数)

    javascript数据结构与算法---检索算法(二分查找法.计算重复次数) /*只需要查找元素是否存在数组,可以先将数组排序,再使用二分查找法*/ function qSort(arr){if (a ...

  10. mysql 按时间累计计算_精通MySQL索引背后的数据结构及算法原理

    本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,mysql支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree ...

最新文章

  1. Dom4j和Xpath(转)
  2. linux 系统管理命令整理
  3. 仿苹果手机闹钟_原来iPhone自带的闹钟这么好用,以前没发现,现在一直在用
  4. CompletableFuture异步调用
  5. python省市区三级联动_Django Admin实现三级联动的示例代码(省市区)
  6. 大数据之-Hadoop完全分布式_集群的启动和停止方式总结---大数据之hadoop工作笔记0039
  7. 几款前端IDE工具:Sublime、Atom、VSCode比较
  8. html如何提取图片颜色代码,解析CSS 提取图片主题色功能(小技巧)
  9. U盘安装CentOS 7解决方案 (fat系统文件4g限制)
  10. three.js学习笔记(十五)——着色器图案
  11. 获取mac电脑最高权限
  12. 掌握计算机基础知识的必要性,浅谈高校开展面向学科门类的计算机基础课程的必要性...
  13. DNS域名服务器的搭建
  14. Binder基石-Parcel
  15. 苹果原壁纸高清_ios14.2壁纸原图高清分享:苹果ios14.2壁纸高清无水印[多图]
  16. 淘宝前后端分离实践(PPT)
  17. RK3288 EDP 调试
  18. mysql 格式化函数总结_Mysql字符串处理函数详细介绍、总结
  19. 看《我的工科女友》感受
  20. python开发ios插件_[原创]Textobot-换个轻松高效的方式开发iOS越狱插件

热门文章

  1. 虚拟机 桥接模式和NAT模式下的ip地址、更改kali虚拟机的网络适配器
  2. Sentaurus TCAD 2013 在RedHat7.0 Linux系统的安装教程
  3. 社区网格员计算机考试考什么,网格员考试内容是什么,网格员考试科目有哪些...
  4. Python调用 dll 文件
  5. 等保2.0 三级检查明细
  6. MAC Unity安装教程
  7. 2021年N1叉车司机免费试题及N1叉车司机模拟试题
  8. Simple allow copy使用Chrome插件复制网站文字
  9. 【操作系统】Ubuntu 16 编译链接 .cpp 和 .asm 文件
  10. 无法打开包括文件的解决办法