【數據結構及算法】3.括號匹配的檢驗


一、題目

◆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++)

View Code
 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下來的必要,所以就寫了這篇博文。

  這個算法難度不大,以后實現二叉樹的非遞歸遍歷的時候再用棧,就沒那么簡單了。


免責聲明!

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



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