括號匹配的檢驗問題(C++)

離安世發表於2020-12-07

資料結構與演算法(括號匹配的檢驗)


括號匹配的檢驗

一、題目

  • 問題描述:

假設表示式中允許有兩種括號:圓括號和方括號,其巢狀的順序隨意,即(()[ ])或[([ ] [ ])]等為正確格式,[( ])或(((]均為不正確的格式。檢驗括號是否匹配的方法可用“期待的緊迫程度”這個概念來描述。例如:考慮下列的括號序列:
[ ( [ ] [ ] ) ]
1 2 3 4 5 6 7 8
當計算機接受了第1個括號以後,他期待著與其匹配的第8個括號的出現,然而等來的卻是第2個括號,此時第1個括號“[”只能暫時靠邊,而迫切等待與第2個括號相匹配的 第7個括號“)”的出現,類似的,因只等來了第3個括號“[”,此時,其期待的緊迫程度較第2個括號更緊迫,則第2個括號只能靠邊,讓位於第3個括號,顯然第3個括號的期待緊迫程度高於第2個括號,而第2個括號的期待緊迫程度高於第1個括號;在接受了第4個括號之後,第3個括號的期待得到了滿足,消解之後,第2個括號的期待匹配就成了最急迫的任務了,…… ,依次類推。可見這個處理過程正好和棧的特點相吻合。

  • 基本要求:
    讀入圓括號和方括號的任意序列,輸出“匹配”或“此串括號匹配不合法”。

  • 測試資料:
    輸入([ ]()),結果“匹配”
    輸入 [( )],結果“此串括號匹配不合法”

  • 實現提示:
    設定一個棧,每讀入一個括號,若是左括號,則作為一個新的更急迫的期待壓入棧中;若是右括號,並且與當前棧頂的左括號相匹配,則將當前棧頂的左括號退出,繼續讀下一個括號,如果讀入的右括號與當前棧頂的左括號不匹配,則屬於不合法的情況。在初始和結束時,棧應該是空的。

  • 選作內容
    考慮增加大括號的情況。

二、程式碼實現

程式碼如下(示例):

#include "iostream"
#include "stdlib.h"
#include "string.h"
#define MAXSIZE 100
#define ERROR 0
#define OK 1
using namespace std;

typedef int Status;
typedef struct{
	char *base;
	char *top;
	int stacksize;
}SqStack;
Status InitStack(SqStack &S){ //初始化一個順序棧 
	S.base = new char[MAXSIZE];
	if(!S.base) exit(ERROR);
	S.top = S.base;
	S.stacksize = MAXSIZE;
	return OK; 
}
Status Push(SqStack &S,char e){ //入棧函式 
	if(S.top - S.base == S.stacksize) return ERROR;
	*S.top++ = e;
	return OK;
}
Status Pop(SqStack &S,char &e){ //出棧函式 
	if(S.top == S.base) return ERROR;
	e = *--S.top;
	return OK;
}
char GetTop(SqStack S){ //取棧頂元素 
	if(S.top != S.base) return *(S.top - 1); 
}
Status StackEmpty(SqStack S){ //判斷順序棧是否為空 
    if(S.base==S.top){
        return true;
    }
    return false;
}
int main(){
	SqStack S;
	char str[20],e,c;
	int t;
	InitStack(S);
	cout<<"輸入要檢驗的式子:"; 
	cin>>str;//輸入要檢驗的式子 
	t = strlen(str);//得出式子字串長度(後面迴圈用) 
	if(str[0] == ')' || str[0] == ']' || str[0] == '}'){
		cout<<"此串括號匹配不合法"<<endl; 
	} //判斷第一個字元;(特殊,需要單獨判斷) 
	for(int i=1;str[i] !='\0';i++){//判斷除第一個字元外的所有字元 
		e = str[i]; 
		c = GetTop(S); //取棧頂元素 
		switch(e){// 選擇函式來進行判斷,後續操作 
			case '(':Push(S,e); break;
			case '[':Push(S,e); break;
			case '{':Push(S,e); break;
			case ')':if(c == '(') Pop(S,e);
			else cout<<"此串括號匹配不合法"<<endl; 
			break;
			case ']':if(c == '[') Pop(S,e);
			else cout<<"此串括號匹配不合法"<<endl; 
			break;
			case '}':if(c == '{') Pop(S,e);
			else cout<<"此串括號匹配不合法"<<endl; 
			break;
			default:break; 
		}
		if((i+1 == strlen(str)) && StackEmpty(S)) cout<<"此串括號匹配"<<endl;
		//給匹配結果寫條件。 
	}
	return 0;
}

三、例項執行

輸入:()
結果:
樣例執行
輸入:(2+3)
結果:
樣例執行
輸入:((]
結果:
樣理執行

總結

這道題,利用了順序棧來進行解決。將“( [ { ) } ]”等符號通過switch函式選擇的方法來進行是否入棧,取棧頂元素的比較,出棧等等…的限定條件來進行結果判斷。
其實利用for函式if函式也能進行實現但是通過最優的解法和程式碼複雜程度,選擇了switch函式。

相關文章