棧的應用——四則運算表達式求值


  最開始的計算器只能進行兩個數之間的運算,而不能進行復雜的如“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('\0' == str[i])/*當對到讀到'\0'時結束遍歷,在這結束時為了將最后一個數字壓入棧頂*/
 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\n", 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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM