zoukankan      html  css  js  c++  java
  • 栈的应用——四则运算表达式求值

      最开始的计算器只能进行两个数之间的运算,而不能进行复杂的如“9+((3*2)+(3-1))/2” 这样的四则运算。后来一名波兰的逻辑学家发明了后缀表达式(或称为逆波兰表达式),非常巧妙地解决了程序实现四则运算的难题。

      后缀表达式是一种把所有运算符都放在运算数字后面出现的式子,所以被称为后缀表达式,这样就解决了运算优先级和括号的问题。而中缀表达式就是我们平常用的标准四则运算表达式,即“9+((3*2)+(3-1))/2”。在计算机计算一个标准四则运算表达式时,都是先将中缀表达式转化为后缀表达式,然后进行计算。

      例如中缀表达式“9+((3*2)+(3-1))/2”转化为后缀表达式“9 3 2 * 3 1 - + 2 / +”。

      中缀表达式转化为后缀表达式规则:

      1、在转化前先建立两个栈,暂且命名为s1和s2。用栈s1存储后缀表达式,用栈s2存储符号;

      2、在转化的过程中需从左到右遍历中缀表达式的每一个数字和符号,若是数字就压入栈s1中即成为后缀表达式的一部分;

      3、若遍历到的是符号,则判断其与栈s2栈顶符号的优先级,若其优先级小于栈顶符号则将栈顶符号依次出栈,并依次压入栈s1,然后将其压入栈s2。若其是右括号则将栈顶符号依次出栈并压入栈s1,直至遇到左括号并将左括号出栈,但不再压入栈s1;

      4、若最后栈s2中还有符号,则将其依次出栈,并压入栈s1。最终完成转化过程。

      中缀表达式转化为后缀表达式:

      以中缀表达式“9+((3*2)+(3-1))/2”的转化为例介绍栈s1和栈s2的情况:

      注:数字和符号的顺序是按在栈中的顺序排列的。

      (1)遍历到字符“9”时:

        栈s1:9 ;

        栈s2:空 ;

      (1)遍历到符号“+”时:

        栈s1:9 ;

        栈s2:+ ;

      (1)遍历到符号“(”时:

        栈s1:9 ;

        栈s2:( + ;

      (2)遍历到符号“(”时:

        栈s1:9 ;

        栈s2:( ( + ;

      (3)遍历到字符“3”时:

        栈s1:3 9 ;

        栈s2:( ( +;

      (4)遍历到符号“*”时:

        栈s1:3 9 ;

        栈s2:* ( ( + ;

      (5)遍历到字符“2”时:

        栈s1:2 3 9 ;

        栈s2:* ( ( + ;

      (6)遍历到符号“)”时:

        栈s1:2 3 9 ;

        栈s2:* ( ( + ;

        此时开始比较,比较之后:

        栈s1:* 2 3 9 ;

        栈s2:( + ;

      (7)遍历到符号“+”时:

        栈s1:* 2 3 9 ;

        栈s2:+ ( +;

      (8)遍历到符号“(”时:

        栈s1:* 2 3 9 ;

        栈s2:( + ( + ;

      (9)遍历到字符“3”时:

        栈s1:3 * 2 3 9 ;

        栈s2:( + ( + ;

      (10)遍历到符号“-”时:

        栈s1:3 * 2 3 9 ;

        栈s2:- ( + ( + ;

      (11)遍历到字符“1”时:

        栈s1:1 3 * 2 3 9 ;

        栈s2:- ( + ( + ;

      (12)遍历到符号“)”时:

        栈s1:1 3 * 2 3 9 ;

        栈s2:- ( + ( + ;

        此时开始比较,比较之后:

        栈s1:- 1 3 * 2 3 9 ;

        栈s2:+ ( +;

      (13)遍历到符号“)”时:

        栈s1:- 1 3 * 2 3 9 ;

        栈s2:+ ( +;

        此时开始比较,比较之后:

        栈s1:+ - 1 3 * 2 3 9 ;

        栈s2:+;

      (14)遍历到符号“/”时:

        栈s1:+ - 1 3 * 2 3 9 ;

        栈s2:/ + ;

      (15)遍历到字符“2”时:

        栈s1:2 + - 1 3 * 2 3 9 ;

        栈s2:/ + ;

      (16)遍历结束,但栈s2中还有符号,所以将栈s2中的符号全部依次压入栈s1中,此时:

        栈s1:+ / 2 + - 1 3 * 2 3 9 ;

        栈s2:空;

       所以后缀表达式为:9 3 2 * 3 1 - + 2 / + ;

       后缀表达式计算结果规则:

      从左到右遍历整个后缀表达式的每一个数字和字符,遇到符号就将处于该符号前的两个数字做当前符号的运算,然后用结果代替原来的两个数字,一直到最终获得结果(栈顶元素即为结果)。

      1 #include<stdio.h>
      2 #include<ctype.h>
      3 
      4 typedef struct node{
      5     char ch;
      6     struct node *next;
      7 }*LinkList;
      8 typedef struct Node{
      9     int num;
     10     struct Node *Next;
     11 }*Linklist;
     12 
     13 int cmp(char c1, char c2);
     14 int counter(int a, int b, char c);
     15 
     16 int main()
     17 {
     18     int i, flag=0, logo;
     19     char str[30];
     20     Linklist Head = new Node, pre, L = new Node;
     21     LinkList head = new node, pot, p, q;
     22     Head->Next = NULL;
     23     L->num = 0;
     24     head->ch = '#';
     25     head->next = NULL;
     26     gets(str);
     27     for(i = 0; ; i++){
     28         if(isdigit(str[i])){
     29             logo = 1;
     30             L->num = L->num * 10 + str[i] - '0';
     31         }
     32         else{
     33             if(logo){
     34                 L->Next = Head->Next;
     35                 Head->Next = L;
     36                 if('' == str[i])/*当对到读到''时结束遍历,在这结束时为了将最后一个数字压入栈顶*/
     37                     break;
     38                 L = new Node;
     39                 logo = L->num = 0;
     40             }
     41             if(head->next != NULL)
     42                 flag = cmp(head->next->ch, str[i]);
     43             else
     44                 flag = cmp(head->ch, str[i]);
     45             if(flag){
     46                 while(head->next){
     47                     pot = head->next;
     48                     if('(' != pot->ch){
     49                         pre = Head->Next;
     50                         pre->Next->num = counter(pre->Next->num, pre->num, pot->ch);
     51                         Head->Next = pre->Next;
     52                         delete pre;
     53                         head->next = pot->next;
     54                         delete pot;
     55                     }
     56                     else if('(' == pot->ch){
     57                         if(1 == flag)
     58                             pot->ch = str[i];
     59                         else{
     60                             head->next = pot->next;
     61                             delete pot;
     62                         }
     63                         break;
     64                     }
     65                 }
     66                 if(!head->next){
     67                     p = new node;
     68                     p->ch = str[i];
     69                     p->next = head->next;
     70                     head->next = p;
     71                 }
     72             }
     73             else{
     74                 p = new node;
     75                 p->ch = str[i];
     76                 p->next = head->next;
     77                 head->next = p;
     78             }
     79         }
     80     }
     81     while(head->next){
     82         pot = head->next;
     83         pre = Head->Next;
     84         pre->Next->num = counter(pre->Next->num, pre->num, pot->ch);
     85         Head->Next = pre->Next;
     86         delete pre;
     87         head->next = pot->next;
     88         delete pot;
     89     }
     90     printf("%d
    ", Head->Next->num);
     91     return 0;
     92 }
     93 
     94 int cmp(char c1, char c2)
     95 {
     96     if('#' == c1)
     97         return 0;
     98     if(')' == c2)
     99         return 2;
    100     if('(' == c2)
    101         return 0;
    102     if('*' == c2 || '/' == c2)
    103         return 0;
    104     if('+' == c2 || '-' == c2){
    105         if('*' == c1 || '/' == c1)
    106             return 1;
    107         return 0;
    108     }
    109 }
    110 
    111 int counter(int a, int b, char c)
    112 {
    113     switch(c){
    114         case '+':
    115             return a+b;
    116         case '-':
    117             return a-b;
    118         case '*':
    119             return a*b;
    120         case '/':
    121             return a/b;
    122     }
    123 }
  • 相关阅读:
    平凡的世界
    MySql启动,提示:Plugin 'FEDERATED' is disabled....Cannot allocate memory for the buffer pool
    MySql开启慢查询报错:Could not open /var/log/slow_query.log for logging (error 13).
    ie浏览器,背景色兼容解决方法
    基于Bootstrap、Jquery的自适应导航栏
    chmod、chown、chgrp的意思
    Can't connect to MySQL server on localhost (0)
    mysql-bin引起mysql不能启动
    文件类型检测
    从数据库中查询规则
  • 原文地址:https://www.cnblogs.com/didideblog/p/7096396.html
Copyright © 2011-2022 走看看