一、題目
◆3.19④ 假設一個算術表達式中可以包含三種括號:圓括號"(" 和
")",方括號"["和"]"和花括號"{"和"}",且這三種括號可按任意的
次序嵌套使用(如:…[…{…}…[…]…]…[…]…(…)…)。編寫判別給定表達
式中所含括號是否正確配對出現的算法(已知表達式已存入數據元素
為字符的順序表中)。
實現下列函數:
Status MatchCheck(SqList exp);
/* 順序表exp表示表達式; */
/* 若exp中的括號配對,則返回TRUE,否則返回FALSE */
順序表類型定義如下:
typedef struct {
ElemType *elem;
int length;
int listsize;
} SqList; // 順序表
Stack是一個已實現的棧。
可使用的相關類型和函數:
typedef char SElemType; // 棧Stack的元素類型
Status InitStack(Stack &s);
Status Push(Stack &s, SElemType e);
Status Pop(Stack &s, SElemType &e);
Status StackEmpty(Stack s);
Status GetTop(Stack s, SElemType &e);
-------------------------------------------------------------------------------------------------
二、思路
檢驗括號是否匹配的方法可以用“期待的急迫程度”這個概念來描述。
例如,考慮下列括號序列:
[ ( [ ] [ ] ) ]
1 2 3 4 5 6 7 8
當計算機接受了第一個括號后,它期待着與其匹配的第八個括號的出現,然而等來的卻是第二個括號,此時第一個括號“[”只能暫時靠邊,而迫切等待與第二個括號相匹配的、第七個括號“)”的出現,類似地,因等來的是第三個括號“[”,其期待匹配的程度較第二個括號更急迫,則第二個括號也只能靠邊,讓位於第三個括號,顯然第二個括號的期待急迫性高於第一個括號;在接受了第四個括號之后,第三個括號的期待得到滿足,消解之后,第二個括號的期待匹配就成為當前最急迫的任務了,……依此類推。
很顯然,這樣的一個處理過程和棧的特點非常吻合,因此,這個問題可以用棧來解決。
解決思路:
1.在算法中設置一個棧,每次讀入一個括號;
2.若是右括號,則或者使置於棧頂的最急迫的期待得以消解,此時將棧頂的左括號彈出;或者是不合法的情況,此時將右括號壓入;
3.若是左括號,則作為一個新的更急迫的期待壓入棧中,自然使原有的在棧中的所有未消解的期待的急迫性都降低一級;
4.在算法的開始和結束時,棧應該為空。
-------------------------------------------------------------------------------------------------
三、代碼(C/C++)

1 Status MatchCheck(SqList exp) 2 /* 順序表exp表示表達式; */ 3 /* 若exp中的括號配對,則返回TRUE,否則返回FALSE */ 4 { 5 Stack s; 6 char e; 7 8 //逐個讀入括號 9 for(int i=0;i<exp.length;i++) 10 { 11 if(exp.elem[i]=='('||exp.elem[i]=='{'||exp.elem[i]=='[')//若遇左括號,則直接入棧 12 { 13 Push(s,exp.elem[i]); 14 } 15 else if(exp.elem[i]==')')//若遇右圓括號,則嘗試匹配棧頂括號 16 { 17 if(GetTop(s,e)) 18 { 19 if(e=='(')//匹配成功,左圓括號出棧 20 { 21 Pop(s,e); 22 } 23 else//匹配不成功,右圓括號入棧 24 { 25 Push(s,exp.elem[i]); 26 } 27 } 28 else//棧為空,則將右括號入棧 29 { 30 Push(s,exp.elem[i]); 31 } 32 } 33 else if(exp.elem[i]=='}')//若遇右花括號,則嘗試匹配棧頂括號 34 { 35 if(GetTop(s,e)) 36 { 37 if(e=='{')//匹配成功,左花括號出棧 38 { 39 Pop(s,e); 40 } 41 else//匹配不成功,右花括號入棧 42 { 43 Push(s,exp.elem[i]); 44 } 45 } 46 else 47 { 48 Push(s,exp.elem[i]); 49 } 50 } 51 else if(exp.elem[i]==']')//若遇右方括號,則嘗試匹配棧頂括號 52 { 53 if(GetTop(s,e)) 54 { 55 if(e=='[')//匹配成功,左方括號出棧 56 { 57 Pop(s,e); 58 } 59 else//匹配不成功,右方括號入棧 60 { 61 Push(s,exp.elem[i]); 62 } 63 } 64 else 65 { 66 Push(s,exp.elem[i]); 67 } 68 } 69 } 70 if(StackEmpty(s))//當所有括號匹配成功時,棧應為空 71 { 72 return TRUE; 73 } 74 else 75 { 76 return FALSE; 77 } 78 }
-------------------------------------------------------------------------------------------------
四、總結
這個算法是在吳偉民教授的《數據結構》里看到的,書上只給出了思想,具體的代碼是我自己寫的,感覺這個問題有mark下來的必要,所以就寫了這篇博文。
這個算法難度不大,以后實現二叉樹的非遞歸遍歷的時候再用棧,就沒那么簡單了。