棧和隊列這一章講的也是兩種非常重要的線性結構,他們也屬於線性表,只是在理解線性表后理解站和隊列會比較得心應手
先來看下棧吧,就像手 槍裝子彈一樣,先放進去的子彈在最下面,最后放進去的子彈為第一槍打出來,棧就是彈夾這個結構,經典說法就是后進先出(last in first out),簡稱LIFO,和線性表一樣,棧也有ADT即抽象數據類型的定義,也有兩種表示方法,順序棧和鏈式棧,一般順序棧用的較多
Typedef struct{
SElemType *base;
SElemTypr *top;
Int stacksize;
}SqStack;
這里用了兩個指針top表示棧頂指針,base表示棧底指針,當top=base時表示空棧。
函數我就不整理了,在具體例題里面體現吧,因為棧的例題還有一部分是很經典的,比如算法3-1數制轉換問題,例如將十進制數轉化為八進制,1348=2504。我們知道用除余法可以解決這個問題,但是先出來的余數要放在最下面,即如圖

具體實現代碼我用了函數封裝來實現:如

圖示為頭文件c3-1.h和算法3.1的程序,在頭文件中,定義了一個順序棧,在算法中調用出來
很簡單就是一個先初始化棧,然后用push函數入棧n%8求余,然后n保存除以8之后的值,出棧的時候用pop函數彈出棧頂元素,然后輸出。
在代碼中用了很多棧的函數如pop,push等,其實可以#include <stack>里面都包含了,但是還是自己實現下會更深刻,我整理如下:

這個bo3-1.cpp也是在算法函數中要調用的,工具函數要實現還是要在頭文件中申明函數的,在棧函數中,其中的追加空間也是很重要的,即判斷棧滿了是否要追加空間,否則程序不能順利進行。
3.2.2是一個括號匹配的檢驗問題,也是一個進棧出棧的問題,如果進棧的括號和前一括號匹配則前一括號出棧如果不匹配則進棧,這樣就實現了較外層的括號永遠在下面優先級就低於內層括號。輸入括號可以用gets(ch),然后設置一個指針*p指向ch,循環p發現左括號就push,發現右括號就pop完整代碼如下:

Case:后面沒有東西說明多個case可以共用一組執行語句,這是多分支選擇結構switch的一個優點,default表示其他,后面可以不用接break,check()函數也不難,一個while和一個switch循環選擇,最后判斷的時候如果棧是空的,即剛好全部匹配完pop后,用if(stackempty(s))來判斷,這道題也不難。
行編輯程序也是一個簡單的棧應用題目,接下來看下最著名的迷宮求解題目
先分析題目,這個是我做的一個迷宮(有點恐怖,紅色的代表通路,黑色的代表牆白色的代表出入口)

用函數定義結構體函數postype(行x列y)來表示每個格子,如上圖的是10行10列
用MazeType[][]數組來存放數據,begin,end 表示入口出口。在初始化迷宮之前約定:
0代表黑色的牆 1代表可以通行 -1代表不可以通行
東南西北一次為 0 1 2 3
初始化迷宮,然后全部賦值為k(通道),除了外牆賦值為0。然后輸入牆的值一個迷宮就建好了。
前期准備工作代碼如下:

接下來實現棧的操作,一樣的定義結構體棧Sqstack,棧的元素類型,struct SElemType 里面包括通道塊在路徑上的“序號”,通道快在迷宮中的“坐標位置”,下一個位置的方向。
定義pass函數,判斷是否可以通過,定義footprint函數,追蹤現在的位置,Markprint函數來標記此處不能通過,Nextpos函數實現方向的選擇,基本函數就這些了,主代碼主要還是運用了棧來求解,從開始位置順時針選擇方向走下去,如果可以通過則入棧,碰到牆就pop然后順時針換方向,一直到end為止,代碼如下:

接下來就是實現主函數了,這個函數才真正體現棧的強大,Mazepath函數,首先把start放在當前位置curpos上,然后開始循環,用pass函數判斷是否通過,通過的話就Footprint留下足跡,記下坐標
然后設置為1即可以通過,然后方向置為0開始循環,將這些信息封裝好入棧,然后足跡cursetp加1,如果到達終點的話,就返回true否則就用nextpos來確定下一個方向,這事pass的函數,如果不pass即當前位置不通過,就要之行pop操作了,同樣上面的操作不過就是足跡減一,然后pop彈出,然后標記-1,如果還有方向可以換,就入棧下一個方向,同樣記錄有關數據,用nextpos來記錄下一個位置的坐標。主函數mazeopath的代碼如下:

這就是完整的迷宮求解問題了。(程序員是命苦= =)
