栈的应用---求表达的值
2015-11-30 12:57
197 查看
一、题目
求一个表达式的值,比如9+(3-1)*3+10/2
二、思路
S1.把中缀表达式转换为后缀表达式
S2.根据后比对表达式得到计算结果
三、中缀表达式、后缀表达式
中缀表达式(或中缀记法)是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:9+(3-1)*3+10/2
),中缀表达式是人们常用的算术表示方法。不容易被计算机解析。
后缀表达式:不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:(2
+ 1) * 3 , 即2 1 + 3 *
四、中缀转后缀(逆波兰算法)
规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于找顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
1.遇到操作数:直接输出(添加到后缀表达式中)
2.栈为空时,遇到运算符,直接入栈
3.遇到左括号:将其入栈
4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算
符入栈
6.最终将栈中的元素依次出栈,输出。
下面我们来具体看看这个过程。
1. 初始化一空栈,用来对符号进出栈使用。
2. 第一个字符是数字9,输出9,后面是符号“+”,进栈。
3. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。
4. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。
5. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”,总的输出表达式为9 3 1 -
6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“*”,因为此时的栈顶符号为“+”号,优先级低于“*”,因此不输出,进栈。
7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +.然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指“9+(3-1)*3+”中的最后一个“+”。
8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。
9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2
10. 因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10 2/+
[align=center]五、根据后缀表达计算结果[/align]
后缀表达式:9
3 1-3*+ 10 2/+
[align=center]规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。[/align]
下面是详细的步骤:
1. 初始化一个空栈。此桟用来对要运算的数字进出使用。
2. 后缀表达式中前三个都是数字,所以9、3、1进栈。
3. 接下来是减号“-”,所以将栈中的1出栈作为减数,3出栈作为被减数,并运算3-1得到2,再将2进栈。
4. 接着是数字3进栈。
5. 后面是乘法“*”,也就意味着栈中3和2出栈,2与3相乘,得到6,并将6进栈。
6. 下面是加法“+”,所以找中6和9出找,9与6相加,得到15,将15进栈。
7. 接着是10与2两数字进栈。
8. 接下来是符号因此,栈顶的2与10出栈,10与2相除,得到5,将5进栈。
9. 最后一个是符号“+”,所以15与5出找并相加,得到20,将20进栈。
10. 结果是20出栈,栈变为空。
[align=center]六、代码(C语言)[/align]
expresstionComputing.h
[align=center]expresstionComputing.cpp[/align]
求一个表达式的值,比如9+(3-1)*3+10/2
二、思路
S1.把中缀表达式转换为后缀表达式
S2.根据后比对表达式得到计算结果
三、中缀表达式、后缀表达式
中缀表达式(或中缀记法)是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:9+(3-1)*3+10/2
),中缀表达式是人们常用的算术表示方法。不容易被计算机解析。
后缀表达式:不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:(2
+ 1) * 3 , 即2 1 + 3 *
四、中缀转后缀(逆波兰算法)
规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于找顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
1.遇到操作数:直接输出(添加到后缀表达式中)
2.栈为空时,遇到运算符,直接入栈
3.遇到左括号:将其入栈
4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算
符入栈
6.最终将栈中的元素依次出栈,输出。
下面我们来具体看看这个过程。
1. 初始化一空栈,用来对符号进出栈使用。
2. 第一个字符是数字9,输出9,后面是符号“+”,进栈。
3. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。
4. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。
5. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”,总的输出表达式为9 3 1 -
6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“*”,因为此时的栈顶符号为“+”号,优先级低于“*”,因此不输出,进栈。
7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +.然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指“9+(3-1)*3+”中的最后一个“+”。
8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。
9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2
10. 因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10 2/+
[align=center]五、根据后缀表达计算结果[/align]
后缀表达式:9
3 1-3*+ 10 2/+
[align=center]规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。[/align]
下面是详细的步骤:
1. 初始化一个空栈。此桟用来对要运算的数字进出使用。
2. 后缀表达式中前三个都是数字,所以9、3、1进栈。
3. 接下来是减号“-”,所以将栈中的1出栈作为减数,3出栈作为被减数,并运算3-1得到2,再将2进栈。
4. 接着是数字3进栈。
5. 后面是乘法“*”,也就意味着栈中3和2出栈,2与3相乘,得到6,并将6进栈。
6. 下面是加法“+”,所以找中6和9出找,9与6相加,得到15,将15进栈。
7. 接着是10与2两数字进栈。
8. 接下来是符号因此,栈顶的2与10出栈,10与2相除,得到5,将5进栈。
9. 最后一个是符号“+”,所以15与5出找并相加,得到20,将20进栈。
10. 结果是20出栈,栈变为空。
[align=center]六、代码(C语言)[/align]
expresstionComputing.h
#define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 typedef int Status; template <class T> class SqStack{ private: T *base; T * top; int stacksize; public: Status InitStack (); Status Push (T e); Status Pop (T&e); Status StackEmpty(); T * getTop(); }; template <class T> T * SqStack<T>::getTop(){ return top; } template <class T> Status SqStack<T>::InitStack () { base = (T *)malloc(STACK_INIT_SIZE * sizeof(T)); if(!base) exit (OVERFLOW); top=base; stacksize=STACK_INIT_SIZE; return OK; } template <class T> Status SqStack<T>::Push (T e) { if (top-base>=stacksize){ base = (T *)realloc(base, (stacksize+STACKINCREMENT) * sizeof(T)); if(!base)exit(OVERFLOW); top=base+stacksize; stacksize+=STACKINCREMENT; } *top++=e; // *S.top = e S.top++ return OK; } template <class T> Status SqStack<T>::Pop (T &e) { if (top==base) return ERROR; e=*--top; return OK; } template <class T> Status SqStack<T>::StackEmpty() { if(top==base) return TRUE; else return FALSE; }
[align=center]expresstionComputing.cpp[/align]
//本程序包含了两个实例:数制转换和计算表达式的值 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <string.h> #include "expressionComputing.h" // 比较两个操作符的优先级 /* -1:op1<op2,op2运算入栈 0:op1 == op2 ,op1出栈 1:op1>op2 , op1出栈 */ //op1:栈顶元素,op2:中缀表达式中的运算符 int Precedence(char op1, char op2) { if (op1 == '(') { return -1; } if (op1 == '+' || op1 == '-') { if (op2 == '*' || op2 == '/') { return -1; } else { return 0; } } if (op1 == '*' || op1 == '/') { if (op2 == '+' || op2 == '-') { return 1; } else { return 0; } } } //把中缀表达式转换成后缀表达式 char * InfixToSuffix(char * str,int length){ SqStack<char> S; S.InitStack(); char * InfixExpression = str; printf("InfixExpression is %s\n",InfixExpression); char * SuffixExpress = (char *) malloc(3*length* sizeof(char)); int i=0; char c; while(*InfixExpression!='\0'){ if(*InfixExpression>='0' && *InfixExpression <= '9'){ *(SuffixExpress+i) = *InfixExpression; i++; // printf("number %c\n",*InfixExpression); //printf("SuffixExpress is %s\n" ,SuffixExpress+'\0'); } else { //判断运算符的进栈与出栈 *(SuffixExpress+i) =' '; i++; if(S.StackEmpty()){ S.Push(*InfixExpression); //printf("push\n"); } else if(*InfixExpression == '(') { S.Push(*InfixExpression); //printf("push ( \n"); }else if(*InfixExpression == ')'){ S.Pop(c); while(c != '('){ *(SuffixExpress+i) = c; i++; *(SuffixExpress+i) = ' '; i++; S.Pop(c); } }else if( Precedence(*(S.getTop()-1),*InfixExpression)>=0){ while(Precedence(*(S.getTop()-1),*InfixExpression)>=0){ S.Pop(c); *(SuffixExpress+i) = c; i++; *(SuffixExpress+i) = ' '; i++; } S.Push(*InfixExpression); }else{ S.Push(*InfixExpression); } } InfixExpression++; } *(SuffixExpress+i) = ' '; i++; while(!S.StackEmpty()){ S.Pop(c); *(SuffixExpress+i) = c; i++; *(SuffixExpress+i) = ' '; i++; } *(SuffixExpress+i) = '\0'; return SuffixExpress; } int caculateValue(char * SuffixExpress){ SqStack<int> S; S.InitStack(); int result=0; int number1; int number2; char *op1 = (char *) malloc(sizeof(char)*20); char *op2 = (char *) malloc(sizeof(char)*20); bool isFirstSpace = true; int i=0; while(*SuffixExpress != '\0'){ printf("current char is %c\n",*SuffixExpress); //把后缀表达式中非运算符的内容都入栈 if(!(*SuffixExpress == '+' || *SuffixExpress == '-' || *SuffixExpress == '*' || *SuffixExpress == '/')){ if(*SuffixExpress == ' ' && isFirstSpace){ //isFirstSpace = false; SuffixExpress++; printf("space is not place to stack\n"); continue; }else if( *SuffixExpress >= '0' && *SuffixExpress <= '9'){ isFirstSpace = false; printf("this is number!\n"); *(op1+i) = *SuffixExpress; i++; printf("pushing char is %c\n",*SuffixExpress); }else { //取到一个操作数,并把在存入栈中 isFirstSpace = true; *(op1+i) = '\0'; S.Push(atoi(op1)); i=0; printf("number is end!\n"); } }else{ //从栈中弹出两个数字,然后进行运算 S.Pop(number2); S.Pop(number1); switch(*SuffixExpress){ case '+': S.Push(number1+number2); break; case '-': S.Push(number1-number2); break; case '*': S.Push(number1*number2); break; case '/': S.Push(number1/number2); break; } } SuffixExpress++; } S.Pop(result); return result; } //包括'\0' int StringLength(char * str){ if(*str == '\0') return 1; else return 1+ StringLength(++str); } void main() { char str[100]; printf("请输入表达式:"); scanf("%s",str); printf("suffixExpress: %s\n",InfixToSuffix(str,StringLength(str))); printf("result is %d\n",caculateValue(InfixToSuffix(str,StringLength(str)))); getchar(); }
相关文章推荐
- [Javascript Practice] 数组扁平化处理
- Android Activity 启动
- iOS9下App Store新应用提审攻略
- samba简单配置
- 日常用语 100 句
- Sqlserver本地服务启动不了,提示请求失败或服务未及时响应
- ScrollView拉到尽头时出现阴影的解决方法
- linux将80端口映射到指定端口命令
- 千万级到10亿+的疯涨,搜狗商业平台服务化体系实践之路
- 如果你是IT技术人员,请思考这15个问题
- Android 蓝牙BLE (蓝牙成长之路)1
- ZPL打印中文
- Jquery according
- 1085. Perfect Sequence
- 实验四外设驱动程序设计报告
- mysql无法启动ERROR! MySQL is running but PID file could not be found ?
- JAVA正则表达式语法大全
- C++标准库中队列的应用
- hibernate一对多
- 《统计学习方法》学习笔记(三)——K近邻法