栈的四则运算

本文章的解决方法参考了《大话数据结构》中关于栈的应用介绍

值得注意的是,书中关于中缀表达式转后缀的讲解中不尽清楚。本人也在这里花了点时间进行推敲错误的原因,也在网上搜到了这篇文章,比较好地介绍了中缀转后缀的的规则

原理:

用计算机求解四则运算,可以使用。因为“先进后出”的特性正好满足了能通过后缀表达式去计算出四则运算式子的结果。而后缀表达式的转化也能使用对中缀表达式进行操作从而转化。明显地,由中缀表达式-》后缀表达式, 后缀表达式-》式子结果。 都需要使用到。所以编码实现中,我们着重的是实现这两个过程的函数(infix_to_suffix()、suffix_to_result()

注意:

测试数据

  • 每个数可以是只达个位的数,也可以达十位以上的数
  • 可以是负数或正数(负数需在两边添加括号)
  • 括号内能存在多个括号,例:( ( 2 + 3 ) + ( 4 + 5 ) + ( ( 6 + 7 ) + 8 ) )

实现

  • 定义了一个全局table用来存储各个运算符的优先级。 + - 等优先级,* / 等优先级, ()不存在优先级(这里主要为了代码实现而取消其优先级)
  • 设置了一个 priority 变量进行存储栈顶元素的优先级,这在中缀转后缀的时候被使用到,并在每次的压栈出栈后,都须对新的栈顶元素进行记录其优先级
  • 在中缀转后缀的函数中,主要包含这几部分:1. 遇到数字直接输出,然后continue  2.左括号直接压栈,然后continue 3. 右括号则将将栈中在左括号以上的所有运算符弹出,然后continue  4. 若是运算符,判断是否优先级比栈顶元素小或相等,若是,则将在左括号前或优先级大于或等于待压栈元素的栈中元素出栈。若不是,则正常压栈,正常压栈过程中需判断是否负数  5.遍历中缀表达式结束后,将栈中还存在的所有元素进行出栈

[cpp]  view plain  copy
 print ?
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4.   
  5. const int MAXSIZE = 100;  
  6. //栈的数据结构  
  7. typedef struct   
  8. {  
  9.     int    data[MAXSIZE];  
  10.     int    top;  
  11. } Stack;  
  12.   
  13. int    table[] = {0,0,2,1,0,1,0,2};//查询运算符优先级表  
  14.   
  15. //函数说明:将中缀表达式转换为后缀表达式  
  16. //参数说明:  
  17. //sta:    转换过程需使用的栈空间  
  18. //infix:  待转换的中缀表达式  
  19. //suffix: 存储转换后的后缀表达式  
  20. //length: 记录后缀表达式的长度  
  21. void infix_to_suffix(Stack *sta, char *infix, int *suffix, int *length);  
  22.   
  23. //函数说明:将后缀表达式转换为结果直接返回  
  24. //参数说明:  
  25. //sta:    转换过程需使用的栈空间  
  26. //suffix: 存储转换后的后缀表达式  
  27. //length: 记录后缀表达式的长度  
  28. int  suffix_to_result(Stack *sta, int *suffix, int length);  
  29. void init(Stack *sta);//栈空间初始化  
  30.   
  31. int main()  
  32. {  
  33.     //这里将标准输入输出流重定向到文件中  
  34. //  freopen("in.txt", "r", stdin);  
  35. //  freopen("out.txt", "w", stdout);  
  36.     Stack     sta;  
  37.     int       length;  
  38.     int       result;         //接受后缀表达式转换的结果  
  39.     int       sstr[MAXSIZE];  //存储后缀表达式  
  40.     char      istr[MAXSIZE];  //存储中缀表达式  
  41.   
  42.     printf("请输入以 + - * / 组成的四则运算\n(注意负数需要在两旁添加上括号)\n");  
  43.     scanf("%s", istr);  
  44.   
  45.     init(&sta); //对栈空间初始化  
  46.     infix_to_suffix(&sta, istr, sstr, &length);  
  47.     init(&sta); //再次对栈空间初始化  
  48.     result = suffix_to_result(&sta, sstr, length);  
  49.   
  50.     printf("%d\n", result);  
  51. //  fclose(stdin);  
  52. //  fclose(stdout);  
  53.     return    0;  
  54. }  
  55.   
  56.   
  57. void infix_to_suffix(Stack *sta, char *infix, int *suffix, int *length)  
  58. {  
  59.     int    i;               //循环变量  
  60.     int    b = 0;           //当数字是十位或以上的时候进行记录  
  61.     int    j = 0;           //suffix数组的下标  
  62.     int    priority = 0;    //记录栈顶元素的优先级  
  63.   
  64.     //for循环的第三表达式不进行i++,将其放在每一次的压栈后或直接输出到suffix进行i++  
  65.     for (i = 0; i < strlen(infix); )  
  66.     {  
  67.         //如果是数字的话,直接放在suffix中,然后continue  
  68.         if (infix[i] >= '0' && infix[i] <= '9')  
  69.         {  
  70.             b = 0;      //谨记每次都需重新赋值为零!  
  71.   
  72.             while (infix[i] >= '0' && infix[i] <= '9')  
  73.             {  
  74.                 b = b * 10 + (infix[i] - '0');  
  75.                 i++;  
  76.             }  
  77.             suffix[j] = b;  
  78.             j++;  
  79.             continue;  
  80.         }  
  81.   
  82.         //如果是右括号的话,将栈中在左括号以上的所有运算符弹出,然后continue  
  83.         if (infix[i] == 41)  
  84.         {  
  85.             while (sta->data[sta->top] != 40)  
  86.             {  
  87.                 suffix[j] = sta->data[sta->top];  
  88.                 sta->data[sta->top] = 0;  
  89.                 sta->top--;  
  90.                 j++;  
  91.             }  
  92.             sta->data[sta->top] = 0;  
  93.             sta->top--;  
  94.             //注意出栈后,须将新的栈顶元素的优先级记录下来  
  95.             priority = table[sta->data[sta->top] % 10];  
  96.             i++;  
  97.             continue;  
  98.         }  
  99.   
  100.         //如果是左括号的话,直接压栈  
  101.         if (infix[i] == 40)  
  102.         {  
  103.             sta->top++;  
  104.             sta->data[sta->top] = infix[i];  
  105.             //注意压栈后,须将新的栈顶元素的优先级记录下来  
  106.             priority = table[sta->data[sta->top] % 10];  
  107.             i++;  
  108.             continue;  
  109.         }  
  110.   
  111.         //如果只是普通的运算符,则压栈  
  112.         if (infix[i] >= 42 && infix[i] <= 47)  
  113.         {  
  114.             //首先比较栈顶元素的优先级是否比入栈元素优先级要大  
  115.             //如果是大于的话,则从栈顶将元素依次出栈后,把待入栈的元素压栈  
  116.             if (priority >= table[infix[i] % 10])  
  117.             {  
  118.                 while (priority >= table[infix[i] % 10] && sta->data[sta->top] != 40)  
  119.                 {  
  120.                     suffix[j] = sta->data[sta->top];  
  121.                     sta->data[sta->top] = 0;  
  122.                     sta->top--;  
  123.                     //注意每次的出栈后,须将新的栈顶元素的优先级记录下来用作比较  
  124.                     priority = table[sta->data[sta->top] % 10];  
  125.                     j++;  
  126.                 }  
  127.                 sta->top++;  
  128.                 sta->data[sta->top] = infix[i];  
  129.                 //注意压栈后,须将新的栈顶元素的优先级记录下来  
  130.                 priority = table[sta->data[sta->top] % 10];  
  131.                 i++;  
  132.             }  
  133.             else   
  134.             {  
  135.                 //这里主要处理负数的提取  
  136.                 if (infix[i] == 45 && sta->data[sta->top] == 40)  
  137.                 {  
  138.                     b = 0;  
  139.                     while (infix[i+1] >= '0' && infix[i+1] <= '9')  
  140.                     {  
  141.                         b = b * 10 + (infix[i+1] - '0');  
  142.                         i++;  
  143.                     }  
  144.                     suffix[j] = b * -1;  
  145.                     sta->data[sta->top] = 0;  
  146.                     sta->top--;  
  147.                     j++;  
  148.                     i += 2;  
  149.                     priority = table[sta->data[sta->top] % 10];  
  150.                     continue;  
  151.                 }  
  152.                 sta->top++;  
  153.                 sta->data[sta->top] = infix[i];  
  154.                 //注意压栈后,须将新的栈顶元素的优先级记录下来  
  155.                 priority = table[sta->data[sta->top] % 10];  
  156.                   
  157.                 i++;  
  158.             }  
  159.   
  160.         }  
  161.     }  
  162.     //把栈中还存在的元素进行弹出  
  163.     while (sta->top != -1)  
  164.     {  
  165.         suffix[j] = sta->data[sta->top];  
  166.         sta->top--;  
  167.         j++;  
  168.     }  
  169.     *length = j;  
  170. }  
  171.   
  172.   
  173. int suffix_to_result(Stack *sta, int *suffix, int length)  
  174. {  
  175.     int    i;  
  176.     int    j;  
  177.     int    result = 0;  
  178.   
  179.     for (i = 0; i < length; i++)  
  180.     {  
  181.         //循环遍历后缀表达式,数字就直接压栈,运算符就取栈顶两个元素出来计算,并将结果压栈  
  182.         switch (suffix[i])  
  183.         {  
  184.         case 42:  
  185.             result = sta->data[sta->top - 1] * sta->data[sta->top];  
  186.             sta->top -= 1;  
  187.             sta->data[sta->top] = result;  
  188.             break;  
  189.         case 43:  
  190.             result = sta->data[sta->top - 1] + sta->data[sta->top];  
  191.             sta->top -= 1;  
  192.             sta->data[sta->top] = result;  
  193.             break;  
  194.         case 45:  
  195.             result = sta->data[sta->top - 1] - sta->data[sta->top];  
  196.             sta->top -= 1;  
  197.             sta->data[sta->top] = result;  
  198.             break;  
  199.         case 47:  
  200.             result = sta->data[sta->top - 1] / sta->data[sta->top];  
  201.             sta->top -= 1;  
  202.             sta->data[sta->top] = result;  
  203.             break;  
  204.         default:  
  205.             sta->top++;  
  206.             sta->data[sta->top] = suffix[i];  
  207.             break;  
  208.         }  
  209.     }  
  210.     return   result;  
  211. }  
  212.   
  213. //初始化栈空间  
  214. void init(Stack *sta)  
  215. {  
  216.     int     i;  
  217.     for (i = 0; i < MAXSIZE; i++)  
  218.     {  
  219.         sta->data[i] = 0;  
  220.     }  
  221.     sta->top = -1;  
  222. }  
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值