這節學習用陣列模擬棧和佇列,這種方法相比內建的棧和佇列,一方面比較通用,不受語言限制,另一方面速度也比較快。而且因為是用陣列模擬的,所以可以對任意位置進行修改(如果有辦法知道要修改的位置的下標的話)。
模擬棧比較簡單, 將陣列的擴充套件方向作為棧的入棧擴充套件方向,並記錄一下棧中的元素數量(其實也就是當前棧頂的位置),每次入棧的時候,先將棧頂位置+1+1
+1,然後在這個位置填入要入棧的資料即可。
需要注意陣列的長度至少需要開到棧最大容量+1+1
+1的大小,因為0
00位置是不存資料的,用來標識棧是否是空的(如果棧頂在0
00位置那麼就是空的)。
模板題:模擬棧。
#include
using
namespace std;
const
int n =
1e5+10;
// 模擬棧:模擬棧陣列、棧頂指標
int stk[n]
, cnt;
intmain()
// 出棧,直接將棧頂指標減少1
else
if(op ==
"pop"
)// 判斷棧是否為空,如果棧頂指標在0那麼就是空
else
if(op ==
"empty"
)// 查詢棧頂元素,直接輸出cnt位置的元素即可
else
}return0;
}
模擬佇列比模擬棧難一點,因為棧是乙個口進出的,所以只需要維護乙個棧頂指標就可以了,棧底永遠在0
00位置(這個位置不存元素)。但是佇列是從隊尾tai
ltail
tail
入隊,從隊頭hea
dhead
head
出隊的。所以入隊的過程其實會讓隊尾tai
ltail
tail
沿著陣列索引的增長方向增長,出隊的過程則會讓隊頭hea
dhead
head
沿著陣列索引的增長方向增長。
所以整個佇列在陣列裡的形態是,隊尾在陣列中離開頭遠的一邊,而隊頭則是衝著陣列的開頭,尾插頭出。
這裡可以讓隊尾指標tai
ltail
tail
初始化在−1-1
−1位置,隊頭指標hea
dhead
head
初始化在0
00位置,則當tailad
tail < head
tail
ad的時候就說明佇列是空的,從語義上講這也是因為不符合佇列在陣列中尾巴在遠端,頭在近端的形態。
同理,在元素入隊時,先把隊尾指標tai
ltail
tail
加1
11,然後再在其位置寫入元素值:
繼續入隊三個元素,也就是繼續往後移動隊尾指標,並寫入數值:
在元素出隊時,直接將隊頭的指標hea
dhead
head
加1
11即可:
持續出隊,直到隊頭指標再次處於超過隊尾指標的位置,模擬佇列就為空了:
在上圖的狀態下,如果繼續入隊,放置的位置是陣列下標為4
44的位置,可以看出,所有在隊頭指標以前的位置都是已經作廢了的位置,這些空間已經無法使用了,這也是這種形式的模擬佇列的一種缺點(在陣列空間有限的情況下,佇列沒法無限持續使用,會產生作廢的空間)。
模板題:模擬佇列。
在下面的實現裡,用hh
表示隊頭指標,初始值為0
,用tt
表示隊尾指標,初始值為-1
。陣列開的空間大小只要按照題目中佇列的操作次數的量級來開就可以了,這樣就算全是入隊操作也不會爆。
#include
using
namespace std;
const
int n =
1e5+10;
// 模擬佇列:模擬佇列陣列、隊頭指標、隊尾指標
int q[n]
, hh, tt =-1
;int
main()
// 出隊,直接將隊頭指標+1
else
if(op ==
"pop"
)// 判斷隊空,只要不滿足tt>=hh就是空的
else
if(op ==
"empty"
)// 查詢隊頭元素,直接輸出隊頭
else
}return0;
}
資料結構學習筆記 棧
它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。這一端被稱為棧頂,相對地,把另一端稱為棧底。向乙個棧插入新元素又稱作進棧 入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成為新的棧頂元素 從乙個棧刪除元素又稱作出棧或退棧,它是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素。p...
資料結構學習筆記 棧
1.定義 棧 stack 是限定僅在表尾進行插入和刪除操作的線性表。根據定義我們知道棧在本質上也是一種線性表,只是在插入和刪除操作上進行了限制。我們把允許插入和刪除的一端稱為棧頂 top 另一端稱為棧底 bottom 不含任何元素的棧稱為空棧。棧又稱為後進先出 last in first out 的...
資料結構學習筆記 棧與佇列
二 佇列 總結參考文獻 棧和佇列的資料操作範圍僅限於邏輯上特定的某端,棧先進後出,佇列先進先出。操作介面 功能返回型別 size 報告棧的規模 intempty 判斷棧是否為空 bool push e 將e插至棧頂 void pop 刪除棧頂物件 ttop 引用棧頂物件 t include vect...