資料結構自學筆記 C語言 棧和佇列

2021-09-24 20:32:55 字數 3407 閱讀 9203

先明確概念,棧和佇列是兩種重要的線性結構,從資料結構角度看,棧和佇列是特殊的線性表,是操作受限的線性表,即限定性資料結構。限定插入和刪除只能在表的端點進行的線性表。

棧的定義和特點

定義:限定僅在表尾進行插入或刪除操作的線性表,表尾——棧頂,表頭——棧底,不含元素的空表稱空棧

特點:先進後出(filo)或後進先出(lifo)

棧的運算:構造空棧、清空棧、銷毀棧、判空棧、取棧頂元素、入棧、出棧

既然棧是特殊的線性表,線性表又分為順序表和煉表,那麼棧自然也分順序棧和鏈棧。

順序棧:順序棧,即棧的順序儲存結構是通過一組位址連續的單元依次存放自棧底到棧頂的資料元素,同時附加指標指向棧頂元素的位址。棧在使用過程中所需最大空間很難估計,因此一般在初始化時先分派乙個基本容量,然後不夠大了在逐段擴大,和之前將的順序表一樣。棧的結構體成員也是三個,但是和順序表有一些差異

由於棧只對棧頂進行操作,所以需要引入top指標,時刻指向棧底,這樣表長還是可以知道的,因為實體地址是連續的,所以用棧頂指標減去棧底指標就是length了,一樣的,只不過換了一種表達形式,順序錶該有的操作還是不變的。

先把順序棧整體**上上來

#include

//printf函式

#include

//malloc函式

#define stack_inin_size 20

//初始分配量

#define stack_increment 10

//每次增量

typedef

struct

seqstack,

*seqstack1;

seqstack1 initstack()

//構造空棧

intisemptystack

(seqstack1 stack)

//判空棧

intcleanstack

(seqstack1 stack)

//清空棧

}int

destroystack

(seqstack1 stack)

//銷毀棧

intpushstack

(seqstack1 stack,

int elem)

//入棧

}*stack->top++

= elem;

return1;

}int

popstack

(seqstack1 stack,

int* e)

//出棧

void

main()

cleanstack

(stack1)

;destroystack

(stack1)

;while(!

isemptystack

(stack1)

)}

鏈棧其實就是鍊錶的簡化版,因為鍊錶找前面比找後面容易,為了滿足filo,在建鍊錶的時候採用反向的方式,在前面的程式裡都有,而且鏈棧不需要頭結點,定義個指標一直指向棧頂就好了。看到網上說,鏈棧一般不需要頭結點,有頭指標就行,自己也就作了一下試了試。其實都一樣,就省了乙個節點的空間,好像也沒太大意義。查了一下資料,使用頭結點的好處就是刪除第乙個資料元素後可以返回表頭,但不實用頭結點,就只剩下乙個指標了,再插入的時候還要新申請空間,重新指過去,這樣鍊錶的初始位置就會一直變。對於是否需要使用頭結點也是有爭議的。但換個方式操作一下會對指標和鍊錶的了解更深入一些,期間也遇到了問題,最後也解決了。看**吧

#include

//printf函式

#include

//malloc函式

#define stack_inin_size 20

//初始分配量

#define stack_increment 10

//每次增量

typedef

struct nodelinkstack,

*linkstack1;

//節點結構

linkstack1 pushstack

(linkstack1 top,

int elem)

//入棧

linkstack1 popstack

(linkstack1 top,

int* e)

//出棧

}void

popstack1

(linkstack1 top,

int* e)

//錯誤出棧

}void

main()

}

這段程式卡的時間太長了,因為犯了乙個很典型的錯誤,總覺得是bug,最後想了很近才想明白。最開始是想和以前一樣,通過傳結構體位址的方式,直接在子函式裡面進行操作就好了,也就是程式裡的錯誤出棧。但是發現每次在子程式裡面的狀態是對的,但一出子程式就還原了,我明明傳遞的是指標啊,指標在子函式可以更改指向位址的內容啊。問題出現在top = top->next;這句話,可以通過指標在子函式中修改指標指向位址內容沒錯,但是不能在子函式中改變指標,其實改的是形參top不是實參top,所以是錯誤的。

棧的filo的特性讓它在遞迴上有很大的應用空間,遞迴就是函式一直呼叫自己,然後一層一層遞迴回去,其實我們從主函式呼叫子函式都是要入棧的,最**的最先出,大家自己感受一下就知道為什麼遞迴要用棧了。

佇列的定義和特點

定義及特點:佇列是限定只能在表的一端進行插入,在另一端進行刪除的線性表,是先進先出(fifo)。隊尾(rear)是允許插入的一端,對頭(front)是允許刪除的一端。佇列和棧正好是相反的,棧是在哪插在哪刪。

佇列和棧的實現方法都是一樣的,其實只要對順序表和煉表熟悉了,這些程式寫起來都是一樣的,就不貼程式了,就用文字數一說。

鏈佇列:由於佇列是一頭進一頭出,所以就需要在之前的鍊錶基礎上在引入乙個尾指標,兩個指標分別指向煉表頭和尾,插入從尾插入,取出從頭取。

順序佇列:順序佇列有乙個問題,就是會假溢位。因為順序佇列是要提前申請號空間的,然後也是兩個指標操作,乙個負責插入,乙個負責刪除。但是當插入端到了申請空間的最後時,有可能前面已經刪除了已經刪除了一些資料元素,也就是說現在佇列並不是滿的,這就是假溢位。假溢位的解決方案是迴圈佇列,把佇列設想成環形,首尾相接,用取餘的方式實現首尾相接。判斷佇列滿的條件是頭指標和尾指標指向同乙個地方。但是這又有新的問題,判斷隊列為空也是頭指標和尾指標指向同乙個地方,所以又提出改進,少用乙個元素空間,當尾指標加一和頭指標指向同乙個地方的時候就判定佇列滿了。

資料結構 棧和佇列(c語言)

棧和佇列是兩種重要的線性結構。從資料結構角度來看,棧和佇列也是線性表,其特殊性在於棧和佇列的基本操作是線性表操作的子集,他們是操作受限制的線性表,因此,可稱為限定性的資料結構。但從資料型別角度看,它們是和線性表大不相同的兩類重要的抽象資料型別。由於它們廣泛應用在各種軟體系統中,因此在物件導向的程式設...

(C語言)資料結構 佇列 棧

12 佇列 queue 入隊 put 出對get 1 2 file queue linkedlist.c 3 4 佇列 queue 5 入隊 put 放在鍊錶尾部,並更新指向鍊錶尾部的指標tail 6 出隊 get 返回並刪除鍊錶頭部節點,並更新指向鍊錶頭部的指標head 7 8 9 include...

C語言資料結構 棧 佇列

ifndef zydl h define zydl h include head.h define stack int size 100 define stackincrement 10 define duqueue max size 10 define maxqsize 100 typedef i...