棧是限定僅在表尾進行插入和刪除操作的線性表。佇列是只允許在一端進行插入操作、而在別一端進行刪除的操作的線性表。
棧是限定僅在表尾進行插入和刪除操作的線性表。我們把允許插入和刪除的一端稱為棧頂。另一端稱為棧底,不含任何資料元素的棧稱為空棧。又稱後進先出線性表(lifo結構)
理解:首先它是乙個線性表,也就是說,棧元素具有線性關係,即前驅後繼關係。只不過它是一種特殊的線性表而已。特殊之處在於限制了這個線性表的插入和刪除位置,它始終只在棧頂進行。這也就使得:棧底是固定的,最先棧的只能在棧底。
棧的插入操作,叫作進棧,也稱壓棧、入棧。
棧的刪除操作,也叫出棧,也有叫作彈棧。
adt 棧(stack)
data
同線性表。元素具胡相同型別,相鄰元素具有前驅和後繼關係
operation
initstack(*s);初始化操作,建立乙個空棧s
destroystack(*s):若棧存在,則銷毀它
clearstack(s):將棧清空
stackempty(s):若棧為空返回true,否則返回false
gettop(s,*e):若棧存在且非空,用e返回s的棧頂元素
push(*s,e):若棧存在,輸入新元素e到棧s中並成為棧頂元素
pop(*s,*e):刪除棧s中棧頂元素,並用e返回其值
stacklength(s):返回棧s的元素個數
endadt
由於棧本身就是乙個線性表,那麼前面學到的線性表的順序儲存和鏈式儲存,對於棧來說,也是同樣適用的。
既然棧是線性表的特例,那麼棧的順序儲存其實也是線性表表順序儲存的簡化,我們簡稱為順序棧。線性表是用陣列來實現的,想想看,對於棧這種只能一頭插入刪除的線性表來說,用陣列哪一端來作為棧頂和棧底較好?對沒錯,下標為0的一端作為棧底比較好,因為首元素都存在棧底,變化最小,所以讓它作棧底。我們定義乙個top變數來指示棧頂元素在陣列中的位置。若儲存棧的長度為stacksize,則棧頂位置top必須小於stacksize。當棧存在乙個元素時,top等於0,因此通常把空棧的判斷條件定為top等於-1;
棧的定義:
typedef
int selemtype
typedef
struct
進棧操作
status push(sqstack *s,selemtype e)
s->top++;
s->data[s->top] = e;
return ok;
}
出棧操作
status pop(sqstack *s,selemtype *e)
進棧出棧沒有涉及到任何迴圈語句,因此時間複雜度均是o(1)
如果我們有兩個相同型別的棧,我們為它們各自開闢了陣列空間,極有可能是第乙個棧已經滿了,再進棧就舉出了,而另乙個棧還有很多儲存空間空閒。這又何必呢,我們完全可以用乙個陣列來儲存兩個棧,只不過需要點小技巧。
陣列有兩個端點,兩個棧有兩個棧底,讓乙個棧底為陣列的始端,即為下標0處,另乙個棧為陣列的末端,即下標為陣列長度n-1處。這樣,兩個棧如果增加元素,就是兩個端點向中間延伸。
關鍵思路是:它們是陣列的兩端,向中間靠攏。top1和top2是棧1和棧2的棧頂指標,可以想象,只要它們不見面就可以一直使用:
棧1空時,top1等於-1;
棧2空時,top2等於n
極端情況下棧2空,棧1的top1等於n-1時,就是棧1滿。反之,當棧1為空時,top2等於0時,為棧2滿。但更多的情況,其實就是我剛才說的,兩個棧見面之時,也就是兩個指標之間相差1時,即top1+1 = top2為棧滿
**如下:
//兩棧共享空間結構
typedef
struct
sqdoublestack;
//壓棧時,除了插入元素值引數外,還需要有乙個判斷是棧1還是棧2的棧號引數stacknumber
status push(sqstack *s,selemtype e, int stacknumber)
if(stacknumber==1)else
if(stacknumber==2)
return ok;
}status pop(sqdoublestack *s,selemtype *e,int stacknumber)
else
if(stacknumber==2)
return ok;
}
都已經有了棧頂在頭部了,單鏈表中比較常用的頭結點也就失去了意義,通常對於鏈棧來說,不需要頭結點的。
對於鏈棧來說,基本不存在棧滿的情況,除非記憶體已經滑可以使用的空間,如果真的發生,那麼此時的計算機系統已面臨宕機崩潰的情況,而不是這個鏈棧是否溢位的問題。
**結構如下:
typedef
struct stacknode
stacknode,*linkstackptr
typedef
struct linkstack
linkstack;
status push(linkstack *s,selemtype e)
status pop(linkstack *s,selemtype *e)
對於空間效能,順序棧需要確定乙個固定長度,可能會存在記憶體空間浪費的問題,但它的優勢是訪問時定位很方便,而鏈棧則要求每個元素都有指標域,這同時也增加了一些記憶體的開銷,但對於棧的長度無限制。
即:如果棧的使用過程中元素變化不可預料,有時很小,有時很大,那麼最好是用鏈棧,反之,如果它的變化的可控範圍內,建議使用順序棧會更好一些。
面試筆記 資料結構 佇列與棧
1.佇列 佇列只允許從它的一端插入資料 隊尾 而從另一端取出資料 隊頭 一般情況下,習慣使用鍊錶作為佇列的儲存結構 typedef struct qnodeqnode,queueptr typedef struct linkqueue 上述 定義了乙個完整的佇列。qnode是佇列的結點型別,然後定義...
資料結構與演算法05 棧 佇列
特點在於只能允許在容器的一端 稱為棧頂端指標,英語 top 進行加入資料 英語 push 和輸出資料 英語 pop 的運算。後進先出 lifo,last in first out 棧描述的是操作,線性表描述的是資料存放鍊錶 操作頭部 順序表 操作尾部 return self.list 是不太合適的 ...
筆記 資料結構 佇列
特性 先進先出,不可根據索引查詢 介面inte ce iqueueds 屬性,佇列中的個數 int getlength 方法,佇列中的個數 bool isempty 佇列是否為空 void clear 清空佇列 void enqueue t item 入隊 t dequeue 出隊 t peek 觀...