栈的应用——四则表达式求值

转载:http://blog.csdn.net/hcx25909/article/details/37816693

谢谢分享!


        栈的应用有很多,四则运算是一个比较常见的应用。对于四则运算,括号内的要先运算,而且还要先乘除后加减,又要涉及到负数和浮点数,看上去简简单单的式子,其实暗藏杀机。

        常用的方法是利用后缀表达式(逆波兰)进行计算。主要分为两步:

        (1)将中缀表达式转化为后缀表达式(栈用来进出运算的符号):

        从左到右遍历中缀表达式的每一个数字和符号,若是数字就输出,既成为后缀表达式的一部分,若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号(乘除优先加减),则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。

(2)将后缀表达式进行运算得出结果(栈用来进出运算的数字)

        从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。

          使用C语言实现的算法:

  1. /*============================================================== 
  2.  *     FileName: expression_calc.c 
  3.  *         Desc: 使用栈完成四则表达式的计算,支持大中小括号以及负数,不支持浮点数 
  4.  *       Author: Hu Chunxu 
  5.  *        Email: huchunxu@hust.edu.cn 
  6.  *      Version: 0.0.1 
  7.  *   LastChange: 2014-07-15 10:07:48 
  8.  *      History: 
  9.  *=============================================================*/  
  10. #include <stdio.h>  
  11. #include <stdlib.h>  
  12. #include <string.h>  
  13.   
  14. #define OK      1   
  15. #define ERROR   0  
  16. #define TRUE    1  
  17. #define FALSE   0  
  18. #define MAXSIZE 50  
  19.   
  20. typedef int Status;  
  21. typedef int SElemType;  
  22.   
  23. //定义一个顺序存储栈  
  24. typedef struct  
  25. {  
  26.     SElemType data[MAXSIZE];  
  27.     int top;  
  28. }SqStack;  
  29.   
  30. /*******************栈的基本操作********************************/  
  31. Status init_stack(SqStack *s)  
  32. {  
  33.     s->top = -1;  
  34.     return OK;  
  35. }  
  36.   
  37. Status clear_stack(SqStack *s)  
  38. {  
  39.     s->top = -1;  
  40.     return OK;  
  41. }  
  42.   
  43. Status stack_empty(SqStack s)  
  44. {  
  45.     if(s.top == -1)  
  46.         return TRUE;  
  47.     else  
  48.         return FALSE;  
  49. }  
  50.   
  51. int stack_length(SqStack *s)  
  52. {  
  53.     return s->top+1;  
  54. }  
  55.   
  56. Status push(SqStack *s, SElemType e)  
  57. {  
  58.     if(s->top == MAXSIZE-1)  
  59.         return ERROR;  
  60.     s->top++;  
  61.     s->data[s->top] = e;  
  62.     return OK;  
  63. }  
  64.   
  65. Status pop(SqStack *s, SElemType *e)  
  66. {  
  67.     if(s->top == -1)  
  68.         return ERROR;  
  69.     *e = s->data[s->top];  
  70.     s->top--;  
  71.     return OK;  
  72. }  
  73.   
  74. /*******************中序表达式转换为后续表达式********************************/  
  75. Status infix_to_postfix(char *infix, char *postfix)  
  76. {  
  77.     SqStack s;  
  78.     int e = 0;  
  79.     int i = 0, j = 0;  
  80.     int flag = 0;  
  81.   
  82.     if(init_stack(&s) != OK)  
  83.         return ERROR;  
  84.       
  85.     while(infix[i]!='\0')  
  86.     {  
  87.         while(infix[i]>='0' && infix[i]<='9')    //如果是数字则输出  
  88.         {  
  89.             if(flag)  
  90.             {  
  91.                 flag = 0;  
  92.                 postfix[j++] = '-';  
  93.             }  
  94.             postfix[j++] = infix[i];  
  95.             i++;  
  96.             if(infix[i]<'0' || infix[i]>'9')  
  97.                 postfix[j++] = ' ';  
  98.         }  
  99.         if(infix[i]==')' || infix[i]==']' || infix[i]=='}')       //如果符号,则进行栈操作  
  100.         {  
  101.             pop(&s, &e);  
  102.             while(e!='(' && e!='[' && e!='{')  
  103.             {  
  104.                 postfix[j++] = e;  
  105.                 postfix[j++] = ' ';  
  106.                 pop(&s, &e);  
  107.             }  
  108.         }  
  109.         else if(infix[i]=='+' || infix[i]=='-')  
  110.         {  
  111.             if(infix[i] == '-' && (i==0 || (i!=0 && (infix[i-1]<'0' || infix[i-1]>'9'))))  //当'-'号处于第一位,或前面是符号时,为负号标志  
  112.                 flag = 1;       
  113.             else if(stack_empty(s))  
  114.                 push(&s, infix[i]);  
  115.             else  
  116.             {  
  117.                 do  
  118.                 {  
  119.                     pop(&s, &e);  
  120.                     if(e=='(' || e=='[' || e== '{')  
  121.                         push(&s, e);  
  122.                     else  
  123.                     {  
  124.                         postfix[j++] = e;  
  125.                         postfix[j++] = ' ';  
  126.                     }  
  127.                 }while(!stack_empty(s) && e!='(' && e!='[' && e!='{');  
  128.                 push(&s, infix[i]);  
  129.             }  
  130.         }  
  131.         else if(infix[i]=='*' || infix[i]=='/' || infix[i]=='(' || infix[i]=='[' || infix[i] == '{')  
  132.             push(&s, infix[i]);  
  133.         else if(infix[i] == '\0')  
  134.             break;  
  135.         else  
  136.             return ERROR;  
  137.         i++;  
  138.     }  
  139.       
  140.     while(!stack_empty(s))  
  141.     {  
  142.         pop(&s,&e);  
  143.         postfix[j++] = e;  
  144.         postfix[j++] = ' ';  
  145.     }  
  146.   
  147.     clear_stack(&s);  
  148.     return OK;  
  149. }  
  150.   
  151. /*******************根据后续表达式计算结果********************************/  
  152. Status calculate(char *postfix, int *result)  
  153. {  
  154.     SqStack s;  
  155.     char *op; //存放后缀表达式中的每个因数或运算符    
  156.     char *buf=postfix; //声明bufhe saveptr两个变量,是strtok_r函数的需要。    
  157.     char *saveptr=NULL;  
  158.     int d,e,f;  
  159.   
  160.     if(init_stack(&s) != OK)  
  161.         return ERROR;  
  162.      
  163.     while((op = strtok(buf, " ")) != NULL)  
  164.     {  
  165.         buf = NULL;  
  166.         switch(op[0])  
  167.         {  
  168.             case '+':  
  169.                 pop(&s, &d);  
  170.                 pop(&s, &e);  
  171.                 f = d+e;  
  172.                 push(&s, f);  
  173.                 break;  
  174.             case '-':  
  175.                 if(op[1]>='0' && op[1]<='9')    //是负号而不是减号  
  176.                 {  
  177.                     d = atoi(op);  
  178.                     push(&s, d);  
  179.                     break;  
  180.                 }  
  181.                 pop(&s, &d);  
  182.                 pop(&s, &e);  
  183.                 f = e-d;  
  184.                 push(&s, f);  
  185.                 break;  
  186.             case '*':  
  187.                 pop(&s, &d);  
  188.                 pop(&s, &e);  
  189.                 f = e*d;  
  190.                 push(&s, f);  
  191.                 break;  
  192.             case '/':  
  193.                 pop(&s, &d);  
  194.                 pop(&s, &e);  
  195.                 f = e/d;  
  196.                 push(&s, f);  
  197.                 break;  
  198.             default:  
  199.                 d = atoi(op);  
  200.                 push(&s, d);  
  201.                 break;  
  202.         }  
  203.     }  
  204.     pop(&s, result);  
  205.     clear_stack(&s);  
  206. }  
  207.   
  208. void main()  
  209. {  
  210.     char infix[MAXSIZE] = {0};  
  211.     char postfix[MAXSIZE] = {0};  
  212.     int result = 0;  
  213.       
  214.     scanf("%s", infix);  
  215.   
  216.     infix_to_postfix(infix, postfix);  
  217.     calculate(postfix, &result);  
  218.   
  219.     printf("%d\n",result);  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值