一、實驗內容
1.實驗目的
棧(Stack)是線性結構的核心內容之一。本實驗要求用高級語言C語言編寫基於棧的順序存儲結構實現棧的入棧、出棧、取棧頂元素和判空操作,並基於上述棧的基本操作實現括號匹配算法,完成實驗報告的填寫,以便加深理解有關棧結構的抽象數據類型等概念,並體會和了解棧結構在日常用戶輸入操作中的應用價值。
2.實驗內容
1) 構建一個棧的順序存儲結構的抽象數據類型,通常應包含如下步驟:
a.定義用來描述順序棧結構的結構體變量類型SqStack;
b.編寫一個順序棧初始化算法,記為InitStack操作(函數);
c.編寫一個順序棧數據元素入棧算法,記為push操作(函數);
d.編寫一個順序棧數據元素出棧算法,記為pop操作(函數);
e.編寫一個取棧頂元素算法,記為GetTop操作(函數);
f.編寫一個判空算法,記為IsEmpty操作(函數);
2)基於上述棧的基本操作實現括號匹配算法:
a.在main函數內部編寫一個括號匹配算法,要求從鍵盤上輸入一個
表達式,判斷這個表達式中的括號是否匹配;
b.測試實驗結果,評估實驗過程.
3)完成實驗報告的填寫
順序棧結構的邏輯結構原理如下:
棧結構的邏輯結構
括號匹配的邏輯結構原理如下:
括號匹配的邏輯結構
利用棧結構后進先出的有限操作特點,通過入棧和出棧的操作來實現對表達式括號匹配正確與否的判斷.
二、實驗過程
1.順序棧結構體定義
首先用C/C++開發環境新建源文件,首先鍵入如下預定義命令行:
圖1 源文件預定義命令行
注意這里需要#include命令行引用string.h頭文件,因為該文件里包含后面操作所需要的strlen庫函數,用於獲取字符串的長度。
接着,根據順序棧的邏輯結構原理圖,定義用來描述順序棧數據對象的結構體變量類型SqStack,代碼如下:
圖2順序棧的結構體類型定義
這里用char作為順序棧數據元素的數據類型,得到SqStack(順序棧結構體變量)的定義。其中用base表示棧底指針,用top表示棧頂指針,用stackSize表示當前棧的大小(即順序棧中數據元素的個數)。
2. InitStack函數
編寫順序棧的初始化操作,首先對傳入的SqStack型參數分配初始大小的存儲空間,這里用100個char的大小來初始化順序棧,如果內存分配失敗則退出程序,否則將S.base賦給S.top,STACK_INIT_SIZE賦給S.stackSize。
代碼如下:
圖3 InitStack函數
3. IsEmpty函數
判空操作:如果棧底指針與棧頂指針相等,則順序棧為空,反之非空。棧是否為空是字符串序列中括號是否匹配的判斷依據。
圖4 IsEmpty函數
4. push、pop和GetTop函數
圖 5 push函數
push函數實現入棧操作,如果棧已滿,則動態增加順序棧的內存,將傳入的參數e賦給當前棧頂指針所指向的棧內元素,賦值結束后棧頂指針自動上移(自加)。
圖 6 GetTop函數
GetTop函數實現取棧頂元素操作,如果棧為空,則操作失敗,否則將棧頂指針的下一位指針所指向的數據元素賦給參數e,賦值結束返回e。
圖 7 pop函數
pop函數實現出棧操作,如果為空,則操作失敗,將棧頂指針的下一位指針所指向的數據元素賦給參數e,賦值結束后棧頂指針自動下移(自減)。
5.括號匹配算法的實現
圖8 括號匹配算法
1. 聲明一個大小為MAXSIZE(宏定義)的char型數組,並初始化;
2. 聲明兩個char型變量m,n;
3. 用char型數組a來接收從用戶界面輸入的字符串序列,getchar用於消化最后一次ENTER鍵字符輸入;
4. length表示字符串的長度;
5. 聲明一個SqStack類型變量並初始化;
6. 用for循環來實現括號匹配的迭代過程,如果迭代獲得的當前字符為(、{、[就調用push函數將字符壓入順序棧中,如果迭代獲得的當前字符為)、}、]就調用GetTop函數取棧頂元素判斷是否與當前字符相等,如果相等則實現出棧操作,如果不相等則輸出“括號不匹配”並返回0退出程序;
7. 如果在for循環中沒有意外退出程序的前提下,繼續進行判空操作,如果順序棧為空,則括號匹配,反之不匹配;
8. 編譯運行,測試代碼.
三、實驗結果
圖9 實驗結果
實驗結果與預期目標一致,能夠正確預測字符串序列是否括號匹配。
四、實驗總結
通過“棧的應用”這個實驗,深入了解到采用棧結構處理日常生活中的用戶操作無處不在,在實現括號匹配算法的過程中,主要利用棧結構后進先出的特性以及棧的入棧、出棧、取棧頂元素和判空操作來實現。其次從鍵盤上輸入一個字符串表達式,判斷這個表達式中的括號是否匹配來測試代碼的正確性。
在實驗的過程中,體會到了棧結構的順序存儲方式的優點,就本實驗而言,由於輸入的表達式數據量不是特別大,順序結構滿足算法的實現。同時節省了一些存儲空間的開銷。
棧結構不僅僅可以用來處理括號匹配的判斷問題,還可以實現函數的遞歸調用,使得程序的運行有確定的入口和出口,為高效地算法實現提供了基礎。
總的來說加深理解有關棧結構的抽象數據類型等概念,並體會和了解棧結構在日常用戶輸入操作中的應用價值。