問題說明:
假設數學表達式中允許包含兩種括號:圓括號“()”和方括號“[]”,嵌套順序任意。
正確的嵌套模式:( [ ] ( ) )、[ ( [ ] [ ] ) ]
正確的表達式例:(a+b)[c*(d-e)]
錯誤的嵌套模式:[ ( ] )、( ( ) ]
比如,在處理表達式(A)時
(A) 4+(2+8)*[5/(9-7)]
有以下步驟:
(1)檢測到第一個括號“(”;
(2)檢測到第二個括號“)”,說明子表達式 “4+(2+8)” 已完成匹配;
(3)檢測到第三個括號“[”;
(4)檢測到第四個括號“(”,與(3)中的括號不匹配,但由於同是左括號,可以繼續匹配;
(5)檢測到第五個括號“)”,由括號的作用可知,后來的括號比先來的括號優先級高,因此與(4)中括號匹配;
(6)檢測到第六個括號“]”,由於原來優先級更高的括號已完成,因此與(3)中括號匹配。至此所有括號匹配完成。
解決方案:
可以看出,匹配成功的條件很簡單:每一個檢測到的括號與已檢測到的優先級最高的括號都匹配。
匹配失敗的條件:
(1)檢測到與已檢測到的優先級最高的括號不匹配的括號;
(2)掃描完整個表達式,還是有已檢測到的括號沒有完成匹配;
由於棧具有“先進后出”的特點,能很好地表現優先級這個性質,因此可以用棧來存儲已經檢測到的括號。
以(A)為例:
有以下步驟:
(1)檢測到第一個括號“(”,進棧;
(2)檢測到第二個括號“)”,進棧。子表達式 “4+(2+8)” 完成匹配,匹配的括號都出棧;
(3)檢測到第三個括號“[”,進棧;
(4)檢測到第四個括號“(”,進棧。與(3)中的括號不匹配,但由於同是左括號,可以繼續匹配;
(5)檢測到第五個括號“)”,進棧。由括號的作用可知,后來的括號比先來的括號優先級高,因此與(4)中括號匹配,匹配的括號都出棧;
(6)檢測到第六個括號“]”,進棧。由於原來優先級更高的括號已完成,因此與(3)中括號匹配。匹配的括號都出棧,至此所有括號匹配完成。
需要注意的是,第一個括號進棧時,沒有比較對象,因此需要特別處理。
判斷函數 judge () 如下:
1 Status judge(Stack *S) 2 { 3 //進行表達式的輸入和判斷 4 SElemType *p; 5 char n; 6 7 scanf("%c",&n); //第一個括號的檢測 8 while(n!='(' && n!='[') //忽略數字等其他符號,直到輸入括號 9 { 10 if(n==')' || n==']' || n=='#') return FALSE; //若為')'或']',則表明不匹配。'#'用於結束輸入 11 scanf("%c",&n); 12 } 13 14 if(n=='(' || n=='[') Push(S,n); //檢測到左括號,進棧 15 scanf("%c",&n); 16 while(n!='#') //'#'用於結束輸入 17 { 18 if(n=='(' || n==')' || n=='[' || n==']') 19 { 20 p=S->top; 21 Push(S,n); 22 if(*(p-1)=='(') //與前一個括號比較 23 { 24 if(*p==')') 25 { 26 printf("%c\n",Pop(S)); 27 printf("%c\n",Pop(S)); 28 } 29 else if(*p==']') return FALSE; 30 } 31 else if(*(p-1)=='[') 32 { 33 if(*p==']') 34 { 35 printf("%c\n",Pop(S)); 36 printf("%c\n",Pop(S)); 37 } 38 else if(*p==')') return FALSE; 39 } 40 } 41 scanf("%c",&n); 42 } 43 if(S->top==S->base) return TRUE; //棧內沒有元素時,說明匹配 44 else return FALSE; 45 }
源代碼如下:

#include <stdio.h> #include <stdlib.h> #define INIT_SIZE 10 #define INCREMENT 5 #define OVERFLOW -2 #define FALSE 0 #define OK 1 #define TRUE 1 #define ERROR 0 typedef char SElemType; typedef int Status; typedef struct stack{ SElemType *base; SElemType *top; int stacksize; }Stack; Status InitStack(Stack *S) { //初始化棧 S->base=(SElemType *)malloc(INIT_SIZE*sizeof(SElemType)); if(!S->base) exit(OVERFLOW); S->top=S->base; S->stacksize=INIT_SIZE; return OK; } Status Push(Stack *S,char e) { //入棧 if(S->top-S->base>=S->stacksize){ //棧滿,重新分配內存 S->base=(SElemType *)realloc(S->base,(INIT_SIZE+INCREMENT)*sizeof(SElemType)); if(!S->base) exit(OVERFLOW); S->top=S->base+S->stacksize; S->stacksize+=INCREMENT; } *S->top++=e; return OK; } char Pop(Stack *S) { //出棧 char e; if(S->top==S->base) return ERROR; //棧空,出錯 e=*(--S->top); return e; } Status judge(Stack *S) { //進行表達式的輸入和判斷 SElemType *p; char n; scanf("%c",&n); //第一個括號的檢測 while(n!='(' && n!='[') //忽略數字等其他符號,直到輸入括號 { if(n==')' || n==']' || n=='#') return FALSE; //若為')'或']',則表明不匹配。'#'用於結束輸入 scanf("%c",&n); } if(n=='(' || n=='[') Push(S,n); //檢測到左括號,進棧 scanf("%c",&n); while(n!='#') //'#'用於結束輸入 { if(n=='(' || n==')' || n=='[' || n==']') { p=S->top; Push(S,n); if(*(p-1)=='(') //與前一個括號比較 { if(*p==')') { printf("%c\n",Pop(S)); printf("%c\n",Pop(S)); } else if(*p==']') return FALSE; } else if(*(p-1)=='[') { if(*p==']') { printf("%c\n",Pop(S)); printf("%c\n",Pop(S)); } else if(*p==')') return FALSE; } } scanf("%c",&n); } if(S->top==S->base) return TRUE; //棧內沒有元素時,說明匹配 else return FALSE; } int main() { Stack Sta; Stack *S=&Sta; printf("INITIALIZING...\n"); if(InitStack(S)) printf("DONE!\n"); printf("enter an expression(stop by '#'):\n"); if(judge(S)==1) printf("It's True!"); else printf("It's False\n"); return 0; }