数据结构之栈的应用——四则表达式求值
来源:互联网 发布: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
- 数据结构之栈的应用——四则表达式求值
- 栈的应用——四则表达式求值
- 栈的应用——四则表达式求值
- 栈的应用——四则表达式求值
- 大话数据结构——栈的应用四则元算表达式求值(后缀表达式计算结果)
- 栈的应用——四则表达式
- 数据结构 栈的应用——算术表达式求值
- 常用数据结构栈的应用—-表达式求值
- 回顾数据结构之栈的应用-表达式求值
- 数据结构(6)--栈的应用之中缀表达式求值
- 数据结构 栈的应用-- 表达式求值
- 【数据结构】栈的应用 I :表达式求值
- 栈的应用-表达式求值-数据结构
- 表达式求值(数据结构-栈的应用 )
- 栈的应用——表达式求值
- 表达式求值——栈的应用
- 栈的应用——表达式求值
- 栈的应用——表达式求值
- Casperjs在Windows系统上的使用方法介绍
- iOS使用xib自定义uiview
- 卡尔曼滤波器-Kalman Filter
- C#里WinForm开发中如何实现控件随窗体大小的改变而自动适应其改变
- C#作为上位机,控制51单片机(下位机),串口通信源程序
- 数据结构之栈的应用——四则表达式求值
- 画段弧线
- Unity学习之切水果游戏
- linux init进程和配置文件inittab
- calabash-ios "No frameworks Group found. Aborting."
- CentOS---网络配置详解
- DSP .c 和.h文件架构
- Linux 常用命令(转)
- 卡尔曼滤波器程序解析(2)