棧的特點
棧的表示
判滿判空
入棧(push)
出棧(pop)
例:用乙個陣列實現兩個堆疊
鏈棧判空
入棧(push)
出棧(pop)
棧的應用舉例
化為字尾表示式
字尾表示式求值
在之前的學習中,我們經常聽說棧,比如:在對比for迴圈與遞迴時,遞迴可能會導致棧溢位。今天就讓我們對棧進行更加深入的**。
棧是限定僅在表尾進行插入或刪除操作的線性表。棧是一種操作受限的線性表,它的基本操作是線性表操作的子集,因此又被稱為限定性的資料結構。
棧的表尾端稱為棧頂。
棧的表頭端稱為棧底。
不含元素的空表。
棧s = ( a1, a2, a3, …, an) ,則a1為棧底元素,an為棧頂元素。
棧的特點是後進先出——把棧想象成乙個一端封閉,一端開口的桶,往桶裡放餅,一層一層的放,若想拿出第乙個放進去的餅,就需要先把它上面的餅拿出去,這就是後進先出。lifo
既然說棧是一種特殊的線性表,那麼相應的,棧也有兩種儲存表示方法:順序棧和鏈棧。
棧的順序儲存結構是利用一組位址連續的儲存單元一次存放自棧底到棧頂的資料元素。
棧的順序儲存結構通常由乙個一維陣列和乙個記錄棧頂元素位置的變數組成
順序棧的定義
。
typedef int position;
struct snode ;
typedef struct snode *stack;
思路
申請陣列最大值 * 結構體大小的空間作為棧的儲存空間
當棧為空時,top值為-1
top代表的是棧頂元素在陣列中位置的下標
code
順序棧的建立
。
stack createstack( int maxsize )
注意:當堆疊為空時,top值為-1.
思路當top的大小與陣列最大下標相等時表示棧已滿
code
順序棧的判滿
。
bool isfull( stack s )
思路
根據定義,top值為-1表示空
code
順序棧的判空
。
bool isempty( stack s )
思路
先判斷堆疊滿不滿,不滿則把新元素放入top + 1的位置
code
入棧操作
bool push( stack s, elementtype x )
else
}
思路
先判斷堆疊空不空,不空則把top位置元素返回
code
入棧操作
elementtype pop( stack s )
else
return ( s->data[(s->top)--] );
}
注意:先變化top還是先進行元素操作?
1.怎麼設計?
2.入棧操作如何實現?
3.出棧操作如何實現?
棧的鏈式儲存結構實際上就是乙個單鏈表。插入和刪除操作只能在鏈棧的棧頂進行。
棧頂指標top應該在鍊錶的哪一頭?
鏈棧的定義
typedef struct snode *ptrtosnode;
struct snode ;
typedef ptrtosnode stack;
思路
構建乙個堆疊頭結點,其下乙個結點指向null
code
鏈棧的建立
stack createstack( )
思路
判斷棧是否為空,只需要判斷頭結點的指向是否為null即可。
code
鏈棧的判空
bool isempty ( stack s )
思路
申請乙個新節點並賦值,另其指向頭結點的下乙個結點,頭結點指向該結點
code
鏈棧的插入
bool push( stack s, elementtype x )
提問:為什麼鏈棧在push操作是不用判斷滿不滿?
思路判別是否是空棧,若不是空棧,則:
1.將待刪除結點賦值給乙個新的結點
2.將待刪除結點的內容賦值給乙個新的變數
3.頭結點指向待刪除結點的下乙個結點
4.釋放新節點記憶體
5.返回新變數
code
鏈棧的刪除
elementtype pop( stack s )
else
}
回溯法是演算法設計中的一種重要思想。
舉個例子:老鼠走迷宮。給定乙個迷宮,老鼠從入口進去,從出口出去。在這個過程中沒有什麼特殊的演算法,只能不斷的試探,試探下一步可以往**走。到了下一步,再去試探接下來的可能性。當到某一步各種可能性都行不通時,就回到上一步的位置再去試探。
這個過程要把試探的路徑儲存起來,若某一次試探不成功,就要回到最近一次試探的狀態。這裡就可以利用堆疊的特性
中綴表示式
運算子位於運算數之間
如: a + b * c - d / e
字尾表示式
運算子位於運算數之後
如: a b c * + d e / -
利用字尾表示式更容易求值,因為在遇到乙個運算時它的運算元已知,所以考慮將中綴表示式轉化為字尾表示式
不帶括號
例: 2 + 9 / 3 - 5 → 2 9 3 + / 5 -
帶括號例: a * ( b + c ) / d → a b c + * d /
思路1.運算數:直接輸出
2.左括號:壓入堆疊(在棧外優先順序高,在棧內優先順序最低)
3.右括號:將棧頂的運算子彈出並輸出,直到遇到左括號(出棧、不輸出)
4.運算子:
· 若優先順序大於棧頂運算子時,則壓棧
· 若優先順序小於等於棧頂運算子時,將棧頂運算子彈出並輸出;再比較新的棧頂運算子,直到該運算子大於棧頂運算子優先順序為止,然後將該運算子壓棧
5.若各物件處理完畢,則把堆疊中存留的運算子一併輸出
例:6 2 / 3 - 4 2 * + = ?
思路1.運算數:入棧
2.運算子:從堆疊中彈出適當數量的運算數,計算並結果入棧
3.最後,堆疊頂上的元素就是表示式的結果值
對於資料結構內容的簡單理解
資料結構 動態陣列 陣列是乙個用來存放相同資料型別變數的容器 它是線性結構的一種 在定義之後開闢一塊下標從0開始的連續空間 它的空間由棧分配 先進後出 filo 優點 得益於其開闢的空間連續,所以陣列隨機訪問性強,查詢速度快 缺點 同樣因為開闢空間的連續性,陣列的空間利用率不高 無法像鍊錶一樣方便大...
資料結構 棧 棧
可以把棧想像成乙個桶 進棧 就是把和桶口一樣大的燒餅往桶裡面扔 出棧 就是把燒餅拿出來 特點 先進後出。先扔進去的燒餅最後才能拿出來,最後扔進去的燒餅,第乙個拿出來 剛開始top 1 top 1 然後把進棧的元素賦值給data top 入棧操作 void push stack s,int x els...
我理解的資料結構(二) 棧(Stack)
其實,實現乙個棧結構非常簡單,我們只需要復用上一節我們自己封裝的陣列就可以快速的實現乙個棧的建立。以陣列的最後乙個元素當成棧頂元素。1.首先,我們先建立乙個棧的藉口,裡面宣告我們需要實現的方法 public inte ce stack注 這裡我們有乙個peek方法,就是檢視棧頂元素,所以我們需要給我...