括號匹配


括號匹配這個問題,說難好難,但是說簡單好像也挺簡單,主要就是看我們的思路是否清晰,條例是否清楚。

基本問題是:給定一串字符,可能包括括號、數字、字母、標點符號、空格,檢查這一串字符中的( ) ,[ ],{ }是否匹配,匹配輸出yes,反之輸出no。

我們可以先確定最基本的邏輯,就是對輸入的數一一判斷,如果是左括號就存起來,等到有有括號的時候進行配對,配對成功繼續輸入,錯了就可以退出了。

於是,數據結構自然而然就是用棧了,而我用的是順序棧。

先說說我最開始的想法啦。

1. 由於首先要讀入一串字符,而且包括空格,但是判斷的時候只能一個一個判斷,所以就先給個數組存這串字符,用下標表示單個字符。

2. 然后為了方便地控制循環,我用strlen取得了字符的長度。

3. 設置了一個result參數,用於表示括號是否匹配的狀態,1表示匹配成功,0表示不匹配。並將其初始化為1,這樣可以避免額外討論字符串中沒有括號的情況。(沒有括號也算匹配成功)

4. 接下來就是匹配環節了。遍歷我們之前的數組,遇到左括號入棧;遇到右括號,把這個右括號和出棧的值嘗試匹配,成功就繼續掃描,失敗不用掃描了,直接輸出no吧。但是由於我用result表示是否匹配,所以我選擇吧result的值變為0,然后退出循環。

5. 遍歷的循環結束后,判斷是否匹配,即判斷result為0還是為1。

看起來沒啥問題,但接着考慮一下,由於我的result初值為1,即默認匹配,會不會存在一種情況使括號即使不匹配,但是由於沒有改變result的值而導致錯誤呢?

那么來看看什么時候result會改變。僅當掃描到右括號才會進行匹配嘗試,而僅當匹配失敗才會使result為0。也就是說,不掃描到右括號,result是沒機會匹配的。

於是我們會想,只有左括號呢?如果沒有對應的右括號,即使不匹配,result仍然為1。

那么就必須額外加一個條件來排除上述情況。顯然這種情況下,棧中一定有左括號,即棧一定非空。那么反過來說,如果括號匹配,棧就一定為空。於是想到最后判斷匹配的條件是:result=1且棧為空。

關鍵代碼如下:

 1 cin.getline(a, 100);
 2     length = strlen(a);        
 3     for (int i = 0; i <= length; i++) {        //
 4         if (a[i] == '(' || a[i] == '[' || a[i] == '{') {        //左括號入棧
 5             Push(stack, a[i]);
 6         }
 7         else if (a[i] == ')' || a[i] == ']' || a[i] == '}') {    //右括號,將其與出棧的字符嘗試匹配
 8             temp = Pop(stack);                                
 9             if (!((a[i] == ')'&&temp =='(' )|| (a[i] == ']'&&temp == '[') || (a[i] == '}'&&temp == '{'))) {
10                 result = 0;            //如果不匹配就將result賦0
11                 break;
12             }
13         }
14     }
15     if (result == 1&&stack.base==stack.top) {        //匹配一定棧空,排除無右括號匹配,只有左括號
16         cout << "yes";
17     }
18     else {
19         cout << "no";
20     }

需要注意的是,棧頂指針所指的一直是頂元素的上一個。因此入棧的時候,現賦值再讓棧頂指針+1;而出棧要反過來,先-1再賦值。一開始我先輸出頭指針的內容再讓頭指針減一,這就導致運行時錯誤。因為我忘了頭指針為棧頂+1,因此其所指沒有確切的值,導致非法訪問。

 


免責聲明!

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



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