动手敲代码——栈(经典问题练习)
2016-09-19 00:05
281 查看
/*用栈实现计算器*/ /*经典的用来练习栈的题目,需要借助逆波兰表达式*/ #include <stdio.h> #include <stdlib.h> #include <assert.h> #define MAXSIZE 64 #define OK 1 #define ERROR 0 typedef struct { int data[MAXSIZE]; int top; }stacknode; /*创建一个顺序栈*/ stacknode * sqstack_create(void) { stacknode * p; p = (stacknode *)malloc(sizeof(*p)); assert(p); //分配空间后加上断言是个好习惯 p->top = -1; return p; } /*入栈操作*/ int sqstack_push(int n, stacknode * p) { if(p->top == (MAXSIZE - 1)) //栈满 { return ERROR; } p->data[++p->top] = n; return OK; } /*出栈操作*/ int sqstack_pop(int *dest, stacknode * p) { if(p->top == -1) //栈空 { return ERROR; } *dest = p->data[p->top--]; return OK; } /*获取栈顶值*/ int sqstack_top(int *dest, stacknode *p) //const修饰指针*p,p指向的内容不可改变 { if(p->top == -1) //栈空 { return ERROR; } *dest = p->data[p->top]; return OK; } /*打印栈中内容*/ int sqstack_print(stacknode *p) { int n = p->top; if(n == -1) //栈空 { return ERROR; } while(n) { printf(" %d ",p->data[n--]); } printf(" %d ",p->data ); printf("\n"); } /*判断栈是否为空*/ int sqstack_is_empty(stacknode *p) { return (p->top == -1); } /*优先级判断函数*/ int get_priority(int ope) { switch (ope) { case '+': case '-':return 1; case '*': case '/':return 2; case '(':return 0; default:return ERROR; } } /*提取两个数和一个操作符进行计算,得到的结果再压栈*/ void compute(stacknode *pnum,int ope) { int num1,num2; int result; sqstack_pop(&num1,pnum); sqstack_pop(&num2,pnum); switch (ope) { case '+': result = num1 + num2; case '-': result = num1 - num2; case '*': result = num1 * num2; case '/': result = num1 / num2; } sqstack_push(result,pnum); } /*进行优先级计算*/ void deal_ope(stacknode *pnum,stacknode *pope,int ope) { int old_ope; if(sqstack_is_empty(pope)||ope == '(') //当空栈或符号为( 时,将符号压栈后返回 { sqstack_push(ope,pope); return; } sqstack_top(&old_ope,pope); //得到栈顶元素 if(get_priority(ope)>get_priority(old_ope)) //比较优先级,入参的符号优先级大于栈顶元素时, 将符号压栈后返回 { sqstack_push(ope,pope); return; } while(get_priority(ope)<=get_priority(old_ope)) { sqstack_pop(&old_ope,pope); compute(pnum,old_ope); //以栈顶符号计算 后压栈 if(sqstack_is_empty(pope)) { break; } sqstack_top(&old_ope,pope); } sqstack_push(ope,pope); //将新的操作符入栈 } //处理括号 ,进行括号里的高优先级计算,之后将计算结果压入数字栈,并且将括号丢弃 void deal_bracket(stacknode *pnum,stacknode *pope) { int old_ope; sqstack_top(&old_ope,pope); //得到符号栈栈顶元素 while(old_ope != '(') { sqstack_pop(&old_ope,pope); //符号栈出栈 compute(pnum,old_ope); //计算后将结果压入数字栈 sqstack_top(&old_ope,pope); //得到栈顶元素,进行下一次循环 } sqstack_pop(&old_ope,pope); //将( 出栈丢去 } int main() { /*str为表达式数组*/ char str[MAXSIZE]; printf("请输入你要计算的表达式:\n"); gets(str); int i = 0; int value = 0; //数字的值 int flag = 0; int old_ope; stacknode *pnum,*pope; // 定义两个指向栈结构体的指针 pnum = sqstack_create(); // 创建存放数字的栈 pope = sqstack_create(); // 创建存放运算符号的栈 /* 表达式字符串解析函数,然后将高优先级的符号/(*)进行计算重新入栈 退出while大家的优先级都一样+-*/ while (str[i] != '\0') { //获取输入的数字 if (str[i] >= '0' && str[i] <= '9')//num { value = value * 10 + str[i] - '0'; flag = 1; } else//ope { if (flag) { //flag = 1说明value里面存储了数字,将其入栈 sqstack_push (value, pnum); //num标志清零,value存放数字的变量清零 flag = 0; value = 0; } if(str[i] == ')') { //如果是右括号,则 deal_bracket(pnum,pope); } else//+-*/(等情况 { deal_ope(pnum,pope,str[i]); } } i++; } //如果flag = 1.说明value里面还有数值,将其入栈 if (flag) { sqstack_push(value,pnum); } //然后将符号与数字依次出栈计算。数字出栈计算完成之后回再次在compute中入栈 while (!sqstack_is_empty(pope)) { sqstack_pop(&old_ope,pope); compute(pnum,old_ope); } //取出数字栈最后剩下的数字,就是最后的答案 sqstack_pop(&value,pnum); //打印结果 printf("%s = %d\n",str,value); return 0; }
相关文章推荐
- 背包问题(空间优化)经典代码
- 史上最全!最经典!最无私的Android资料(书籍+代码)分享-不要积分(求置顶)!- ORIEtech[问题点数:100分]
- Scala 深入浅出实战经典 第98讲:使用SBT开发时动手解决rt.jar中CharSequence is broken等问题
- 动手敲代码——递归(汉诺塔问题)
- 我写的PHP集成FCK的经典代码 -- vb2005xu自己动手
- 经典面试智力题(过桥问题)及完整java代码
- 动态规划问题中的几个经典问题代码
- Scala 深入浅出实战经典 第95讲:Akka第一个案例动手实战MasterActor代码详解
- TCP网络传输“粘包”问题,经典解决(附代码)
- 从一段经典错误代码说起——关于局部变量指针和函数传参的问题分析
- Cosmos动手练习(基于里程碑2的代码)--.net/C#开源操作系统学习系列十
- 帮初学者改代码——playerc之“练习:求完数问题”(上)
- 平时代码练习----#prama pack、字符串的字节数问题
- Scala 深入浅出实战经典 第96讲:Akka第一个案例动手实战main方法实现中ActorSystem等代码详解
- 自己动手写中文分词解析器完整教程,并对出现的问题进行探讨和解决(附完整c#代码和相关dll文件、txt文件下载)
- 学习笔记---递归的代码,解决经典的汉诺塔问题
- 入门经典-p130-倒水问题代码解析
- 自己动手写中文分词解析器完整教程,并对出现的问题进行探讨和解决(附完整c#代码和相关dll文件、txt文件下载)
- 算法竞赛入门经典,练习代码 ,4.4.1 小问题集锦
- 经典面试编程题--atoi()函数的实现(就是模拟手算,核心代码就一句total = 10 * total + (c - '0'); 但是要注意正负号、溢出等问题)