利用順序棧解決括號匹配問題(c++)-- 數據結構


 

 

題目:

7-1 括號匹配 (30 分)
 

給定一串字符,不超過100個字符,可能包括括號、數字、字母、標點符號、空格,編程檢查這一串字符中的( ) ,[ ],{ }是否匹配。

輸入格式:

輸入在一行中給出一行字符串,不超過100個字符,可能包括括號、數字、字母、標點符號、空格。

輸出格式:

如果括號配對,輸出yes,否則輸出no。

輸入樣例1:

sin(10+20)

輸出樣例1:

yes

輸入樣例2:

{[}]

輸出樣例2:

no


分析:

通過詳讀題目以及例題我們可以知道:程序會讀入隨機輸入的一串字符串,而當只有 '('和')' 、'['和']' 、 '{'和'}'相匹配的時候輸出“yes”,其他情況都會輸出“no”。

這時候我們可以采用順序棧的結構來解決這一個問題:
將所有的左括號(即" ( 、[ 、{ ")存入棧中,遇到右括號(即" )、]、}")時出棧,再判斷兩者是否匹配。



代碼:

#include<iostream>
#include<string.h>
using namespace std;
 
//定義棧 
#define max_size 200//棧的最大容量 
typedef char datatype;
typedef struct{
          datatype zhan[max_size];
          int top;//棧頂 
}stack;
 
 

//棧的初始化
void initial(stack &st)
{
 st.top = 0;
}
 
 

//類型為datatype的x入棧 
void push(stack &st, datatype x)
{
    //當棧頂和max_size相等時,棧滿 
           if(st.top == max_size){
                 // cout<<"This stack has already full!";
                 cout<<"no";
                 exit(0);
           }else{
                 st.zhan[st.top] = x;
                 st.top++;
           }
}
 
 
 
//出棧 
char pop(stack &st){
          if(st.top == 0){
               // cout<<"This stack is empty!";
               cout<<"no";
               exit(0);
          }else{
               st.top--;
               return st.zhan[st.top];
          }
} 
 
 
 
int main(){
 
 stack s;
 initial(s);
 
 /*輸入字符串,並將字符串放到字符數組中,
 實現能夠逐個掃描字符串中的字符,並且不跳過空格符 
 */ 
 string str;
 getline(cin, str);
 char ch[200]={'\0'};
 strcpy(ch,str.c_str());
 
 
 
 //flag標志狀態 1為括號匹配,0為不匹配 
 int flag=1; 
 int i;
 for(i=0; ch[i]!='\0'; i++){
          //元素若為{,(,[則入棧
          if((ch[i] == '{' )|| (ch[i] =='[') || (ch[i] =='(')){
                  push(s, ch[i]); 
           }//元素若為},),]則出棧 賦值給a 
           else if((ch[i] == '}') || (ch[i] ==']') || (ch[i] ==')')){ 
                  char a;
                  a = pop(s);
                  //若a與ch[i]匹配,進行下一個字符掃描 
                  if((a == '{' && ch[i] == '}') || (a == '(' && ch[i] == ')') || (a == '[' && ch[i] == ']')){
                            continue;
                  }else flag = 0; 
            } 
 }
 
 if(s.top != 0){    //當左括號多出沒有與右括號匹配的時候(如:" {() ")
  flag = 0
 } 
 
 if(flag == 0){
  cout<<"no";
 }else cout<<"yes";
 return 0;
}

 

 

 
編程過程中遇到的問題:
 
1.  在對字符串進行入棧操作時s.top(棧頂)的數值不增加,總為1
 
錯誤代碼如下:
 
 
 
 
運行結果如下:
 
 
這段代碼對於初學者來說看上去邏輯和操作過程似乎都沒有問題,同時也困擾了我許久,
在參考了《數據結構(c語言版)》李雲清等編著的教程后,我發現我犯了一個致命的低級錯誤:
編程push函數的時候,傳入的參數為 stack st ,是不具有返回的功能,也就意味着在 push 函數中對於 st.top++ 這個操作沒有更改主函數中st.top的數值。
 
 
修改代碼如下:
 
將傳入的參數為 stack st 改為 => 傳入的參數為 stack &st,
當然,將它寫成具有返回值的函數或者傳入指針也是可行的。
 
 
 
2. 字符串入棧時,每個字符都入棧,沒有通過是否為左括號(即" ( 、[ 、{ ")的判斷
 
錯誤代碼如下:
 
 
 
運行結果如下:
 
此運行結果為debug時設置的多點輸出,數字均為 s.top ,加個a只是區分兩個地方...
 
 
 
這樣看我們的push函數!又似乎沒有什么問題對不對!
 
但實際上if里面的語句是有問題的,受到多年數學的影響,判斷是否為左括號,不能寫成  "  ch[i] == '{' || '[' || '('  " ,
而需要修改為: "   (ch[i] == '{' )|| (ch[i] =='[') || (ch[i] =='(')   "
 
修改后代碼:
 
那么另一個低級錯誤也就告一段落了...
可見基礎中的基礎的重要性啊!
 
 
 
3.  運行pop函數時,沒有字符的返回
 
錯誤代碼如下:
 
 
 
運行結果如下: 
 
第一個數字1為調用push后的flag , 第二個數字0為調用push和pop后的flag
 
 
 
 
 
從運行結果我們可以看到,理應出棧的 " ) " 和 " } "都是沒有正常顯示出來的,
也就是沒有正常的返回給錯誤代碼中的 datatype x 。
一開始我以為是在 函數傳入形參的時候,利用引用值返回x 的這種方法並不行,於是我又將它改寫成利用含有返回值函數返回我們需要的 x 這種方法(如上圖錯誤代碼所示)
但是結果都是一模一樣的,這時候我就揪着這個函數看,很明顯的,既然錯誤不在傳入傳出的參數中那么只能出現在if{....} 或 else{...}的語句中(顯而易見,是在else{...}中)
bug也很容易看出來了,畢竟也就只有兩句。
 
 
 
修改代碼如下:
 
其實改完回來再看的時候也覺得很無語,第一個入棧的字符(有且只有一個入棧)是在 st.zhan[ 0 ]  中存放的,
而再錯誤代碼中我首先pop出來的卻是  st.zhan[ 1 ]  ,並沒有這個字符,程序當然會出錯啦。
 
 
 
 
 

總結:
 
在這種調用多個函數的這種題目中,debug 可能是最考驗人意志力的一步了
最后再強調一遍: 
 
基礎真的很重要!!!
 
&&
 
如有不正確的地方或有值得改進的地方,希望各位大佬指點一下。
:)
 
          


免責聲明!

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



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