数据结构之栈的应用——四则表达式求值

来源:互联网 发布:nba2kol刷球星软件 编辑:程序博客网 时间:2024/06/10 09:20
栈的应用——四则运算表达式求值

步骤:
 ①把四则运算表达式转换为后缀表达式
          规则:初始化一空栈,用来对符号进出栈的使用
                    从左往右遍历每个数字和符号,若是数字就输出,成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号则栈顶元素依次出栈并输出,然后将当前符号进栈,一直到最终输出后缀表达式为止
     ②计算后缀表达式
          规则:初始化一个空栈,用来对要运算的数字进出栈的使用
                    从左到右比遍历表达式的每个数字和符号,遇到数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果


一点小感悟:
1.左括号只有碰到右括号时才出栈
2.优先级高的运算符必须先出栈,转换为后缀表达式的时候才可以先运算.因为一个运算符的优先级高低是由其前后符号相比而能够确认的
3.之所以符号栈中需要先进一个运算符并且只有碰到优先级比自己低的运算符才出栈是为了在计算后缀表达式的时候不会存在一个数字栈中只有一个数字而不能进行运算的情景(感觉是这样)
4.当用线性存储结构来实现栈时,需要明确的是当删除一个元素时,实际上并没有删除,只是不能够访问到,就好比删除一样;当插入一个元素时(在出栈操作之后),其实只是覆盖了原有的值而已

实现代码如下:
#include<stdio.h>#define size 30//长度#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0typedef int Status;typedef struct {char str[size];//装元素的栈int top;//用于栈顶的指针}calculate;Status initStack(calculate *calculate){//初始化栈calculate->top = -1;return OK;}Status push(calculate * calculateStack , char ch){//把ch进栈calculateif(calculateStack->top == size - 1){//如果栈满,则不能进栈return FALSE;}calculateStack->top ++;//栈顶指针向上移一位calculateStack->str[calculateStack->top] = ch;//栈顶元素为chreturn OK;}Status pop(calculate * Stack,char *ch ){//出栈if(Stack->top == -1){//不为空栈return FALSE;}*ch = Stack->str[Stack->top];Stack->top--;return OK;}/*//把四则运算式转换为后缀表达式因为是用字符串来实现,所以会存在一个问题就是一个数拥有多位数时,进栈出栈会被拆分,而之后会存在问题。所以需要方法来解决本人解决办法:出栈的数字和运算符+-* / 用array数组来记录,元素与元素之间用空格隔开,所以就可解决问题flag参数是用来判断是否是属于一个数字的*/Status changeToSuffix(char *string,calculate *calculate,char *array){int flag = 0;int i = 0;int j = 0;char ch;for( ; string[i] != '\0' ; i++){//一直循环,直到字符串末尾switch(string[i]){//根据不同字符会有不同结果case '(':push(calculate,string[i]);//做括号直接进栈,直到遇到有括号才出栈flag = 0;//表示这个字符不是数字,为后面判断多位数时做准备,以下同理break;case ')'://右括号不进栈,把符号栈中左括号上的符号一次出栈while(calculate->str[calculate->top] != '('){pop(calculate,&ch);//运算符号出栈array[j] = ch;//array记录j++;//用空格分隔元素array[j] = ' ';j++;flag = 0;}pop(calculate,&ch);//左括号出栈,不需要记录break;case'*'://这里判断运算符的优先级利用了ASCII码值,当符号栈calculate中有优先级与*一样的就出栈,直到遇到优先级低的或者左括号,出栈条件是符号栈不是空栈while(calculate->str[calculate->top] !='(' && calculate->str[calculate->top] - string[i] !=3 && calculate->str[calculate->top] - string[i] != 1  && calculate->top != -1){if(calculate->top != -1){pop(calculate,&ch);array[j] = ch;j++;array[j] = ' ';j++;}}push(calculate,string[i]);//当前符号进栈flag =0;break;case '/'://与*相同,其实可以和*写在一块while(calculate->str[calculate->top] !='(' && string[i] - calculate->str[calculate->top] !=2 && string[i] - calculate->str[calculate->top] != 4 && calculate->top != -1){if(calculate->top != -1){pop(calculate,&ch);array[j] = ch;j++;array[j]=' ';j++;}}push(calculate,string[i]);flag =0;break;case'+':case'-'://没有比加减的优先级更低的运算符,所以直到遇到左括号或者符号栈为空栈时才停止出栈while(calculate->str[calculate->top] !='(' && calculate->top != -1 ){if(calculate->top != -1){pop(calculate,&ch);array[j] = ch;j++;array[j] = ' ';j++;}}push(calculate,string[i]);flag = 0;break;default: //数字,当flag为1时,说明上一个字符也是数字,所以需要和此数字字符连在一起if(flag ==1){j--;//把' ' 变为这个字符array[j] = string[i];}else{array[j] =string[i]; }j++;array[j] = ' ';j++;flag = 1;}}while(calculate->top != -1){//当所有数字都已记录时,需要把符号栈中剩下的符号全部出栈pop(calculate,&ch);array[j] = ch;j++;array[j]= ' ';j++; }array[j] = '\0';return OK;}/*------------------------------------------------------------------------------------------------------------计算后缀表达式,并输出结果。因为数字是字符串组成(如123),所以需要调用函数changeToNumber转换为相应数字并需要一个int类型的数栈  */typedef struct//数字栈,用于数字进栈出栈{int numbers[size];int top;}numberStack;Status initNumberStack(numberStack *NumberStack){ //初始化栈NumberStack->top = -1;return OK;}Status pushNumber(numberStack * stack , int number){//把ch进栈calculateif(stack->top == size - 1){//如果栈满,则不能进栈return FALSE;}stack->top ++;//栈顶指针向上移一位stack->numbers[stack->top] = number;//栈顶元素为numberreturn OK;}Status popNumber(numberStack * stack,int* number ){//出栈if(stack->top == -1){//不为空栈return FALSE;}*number = stack->numbers[stack->top];stack->top--;return OK;}int getLength(char * numberstr){//获取数字字符串的长度,为转化为实际数字做准备int i = 0;while(numberstr[i] != '\0' ){i ++;}return i;}int changeToNumber(char * numberstr ,int length){//转化为数字,length为数字字符串的长度int i = length-1;//下标从0开始,所以减1int number = 0;int ten = 1;for( ; i >= 0; i-- ){number = number + (numberstr[i] - '0')*ten ;ten = ten * 10 ;}return number;}int Calculate(numberStack *stack , char * array){//把后缀表达式计算值char numberstr[7] ;//数字字符串int number;//存储数字字符串转化为的数字int numbertop;//存储数字栈中栈顶的数字int numberundertop;//存储数字栈中栈顶下面的那个数字int length;//存储数字字符串的长度,相当于是数字的位数int i;int j =0;int result;//计算结果for(i = 0; array[i] != '\0'; i++){switch(array[i]){case ' ' ://中间分隔符:空白符,不做任何处理break;case '+'://取出栈的上面两个数字,进行运算,把计算结果放入栈顶popNumber(stack,&numbertop);popNumber(stack,&numberundertop);pushNumber(stack,numberundertop + numbertop);break;case '*':popNumber(stack,&numbertop);popNumber(stack,&numberundertop);pushNumber(stack,numberundertop * numbertop);break;case '-':popNumber(stack,&numbertop);popNumber(stack,&numberundertop);pushNumber(stack,numberundertop - numbertop);break;case '/':popNumber(stack,&numbertop);popNumber(stack,&numberundertop);pushNumber(stack,numberundertop/numbertop);break;default://取出数字,直到晕倒空白符,表示这个数字结束while(array[i] != ' ' && array[i] != '\0'){numberstr[j] = array[i];j++;i++;}numberstr[j]='\0';length = getLength(numberstr);//获取数字的长度number = changeToNumber(numberstr,length);//转化为数字pushNumber(stack,number);//把数字放入栈顶j = 0;}}result = stack->numbers[stack->top];//最后栈顶的元素值就是计算结果stack->top = -1;return result;}void main(){calculate calculateStack;//存放四则运算符的栈char string[size] = "9+(3-1)*3+10/2";//四则运算式子char arr[size] ;//存储后缀表达式char *array = arr;int result;//计算结果numberStack numbers;//运算后缀表达式所用到的数字栈initStack(&calculateStack);changeToSuffix(string,&calculateStack,array); //调用函数,转化为后缀表达式printf("%s\n",array);initNumberStack(&numbers);result = Calculate(&numbers,array);//计算后缀表达式printf("%d\n",result);1}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 申请微信公众号邮箱已被占用怎么办 公众号验证没有对公账户怎么办 qq密码忘记了怎么办手机绑定没有 我的扣扣怎么申诉都找不回来怎么办 装修装的不好又没有签合同怎么办 日本免税的零食不小心拆了怎么办 闲鱼同意买家退货了买家不退怎么办 手机里淘宝钱付了不发货怎么办 百度云下载手机储存空间不足怎么办 苹果8的照片储存空间满了怎么办 为什么下载的软件已停止运行怎么办 苹果手机刷机忘记注册邮箱了怎么办 刺激战场模拟器注册已达上限怎么办 用模拟器玩刺激战场注册上限怎么办 微信解除实名认证后退款怎么办 苹果为什么qq收消息有延迟怎么办 qq忘记密码手机号也换了怎么办 扣扣空间圈人时照片服务错误怎么办 删了qq好友怎么找回来怎么办 苹果5s语音控制打开了怎么办 lv迷你水桶包肩带长了怎么办 在香港买个lv包包过海关怎么办 国际快递手表被海关查应该怎么办 把档案放到人才市场后报到证怎么办 皮表带带久了有异味怎么办 英语中用词不当和拼写错误怎么办 爬楼梯的购物车车轮坏了怎么办? 帮别人买东西不给我钱怎么办 老师念错名字有同学指出来你怎么办 老公婚前买的房子婆婆想霸占怎么办 我想查我的基金收益情况怎么办 儿童票买好了但大人退票了怎么办 没有享受到国家政策的农民怎么办? 股票涨了没抛然后一直跌怎么办 苹果手机放久了开不了机怎么办 部门要辞退你你不想走该怎么办 口头说辞职现在又不想走了怎么办 网上买的理财不给退本金怎么办 买东西遇到态度不好的人你会怎么办 app在下载东西时被停用了怎么办 买东西填错地址 但已签收怎么办