資料結構學習筆記(特殊的線性表 棧與佇列)

2022-05-17 08:59:05 字數 3668 閱讀 1247

棧與佇列

棧是限定僅在表尾(棧頂)進行插入和刪除操作的線性表(後進先出)。

佇列是只允許在一端進行插入操作,而在另一端進行刪除操作的線性表(先進先出)。

棧(stack):

1.下標為0的一端作為棧底比較好,因為首元素都存在棧底,變化最小,所以讓它作為棧底。

定義乙個top變數來指示棧頂元素在陣列中的位置。棧頂位置top必須小於儲存棧長度stacksize,把空棧的判定條件定位top等於-1。

2.進棧與出棧操作(順序儲存結構):

進棧操作push:

/*插入元素e為新的棧頂元素*/

status push(sqstack *s, selemtype e)

出棧操作pop:

/*若棧不空,則刪除s的棧頂元素,用e返回其值,並返回ok;否則返回error*/

status pop(sqstack *s, selemtype *e)

*進棧與出棧兩者的時間複雜度均是o(1)。

3.兩棧共享空間:

陣列有兩個端點,兩個棧有兩個棧底,讓乙個棧的棧底為陣列的始端,即下標為0處,另乙個棧為棧的末端,即下標為陣列長度n-1處。這樣,兩個棧如果增加元素,就是兩端點向中間延伸。

棧1為空時,就是top1等於-1時;而當top2等於n時,即是棧2為空時。

兩個棧見面知識,也就是兩個指標之間相差1時,即top1 + 1 == top2 為棧滿。

4.棧的鏈式儲存結構:

棧頂放在單鏈表的頭部。

對於鏈棧來說,是不需要頭結點的。

對於鏈棧來說,基本不存在棧滿的情況。

鏈棧的空其實就是top=null。

5.進棧與出棧操作(鏈式儲存結構):

進棧操作:

/*插入元素e為新的棧頂元素*/

status push(linkstack *s, selemtype e)

出棧操作:

/*若棧不空,則刪除s的棧頂元素,用e返回其值,並返回ok;否則返回error*/

status pop(linkstack *s, selemtype *e)

*鏈棧的出棧push和出棧pop操作沒有任何迴圈操作,時間負責度均為o(1)。

*順序棧和鏈棧,它們在時間複雜度上是一樣的,均為o(1)。

*如果棧的使用過程中元素變化不可預料,有時很小,有時非常大,那麼最好是用鏈棧;反之,如果它的變化在可控範圍內,建議使用順序棧會更好一些。

6.棧的應用:遞迴

遞迴定義:把乙個直接呼叫自己或者通過一系列的呼叫語句間接地呼叫自己的函式,稱作遞迴函式。

每個遞迴定義必須至少有乙個條件,滿足時遞迴不再進行,即不再引用自身二十返回值退出。

*迭代和遞迴的區別是:迭代使用的是迴圈結構,遞迴使用的是選擇結構。遞迴能使程式的結構更清晰,更簡潔,更容易讓人理解,從而減少讀懂**的時間。但是大量的遞迴呼叫會建立函式的副本,會耗費大量的時間和記憶體。迭代則不需要反覆呼叫函式和占用額外的記憶體。

遞迴過程退回的順序是它前行順序的逆襲。

7.棧的應用:四則運算表示式求值

字尾表示式:所有的符號都是在要運算數字的後面出現。

中綴表示式:標準四則運算表示式。

*字尾表示式運算規則:從左到右遍歷表示式的每個數字和符號,遇到數字就進棧,遇到是符號,就將處於棧頂兩個數字出棧,進行運算(後出棧的那個數字是「被」的,比如「被減數」,前面那個比如「減數」,運算結果出棧,一直到最終獲得結果。

*中綴表示式轉字尾表示式:

規則:從左到右遍歷中綴表示式的每個數字和符號,若是數字就輸出,即成為字尾表示式的一部分;若是符號,則判斷其與棧頂符號的優先順序,是右括號或優先順序低於棧頂符號(乘除優先加減)則棧頂元素依次出棧並輸出,並將當前符號出棧,一直到最終輸出字尾表示式為止。

佇列(queue):

1.佇列定義:佇列是只允許在一端進行插入操作,而在另一端進行刪除操作的線性表。

佇列是一種先進先出的線性表。允許插入的一端稱為隊尾,允許刪除的一端稱為隊頭。

2.把佇列的這種頭尾相接的順序儲存結構稱為迴圈對列。

3.判斷佇列究竟是空還是滿?

*辦法一是設定乙個標誌變數flag,當front == rear,且flag = 0 時為佇列空,當front == rear,且 flag = 1時為佇列滿。

*辦法二是當佇列空時,條件就是front = rear,當佇列滿時,我們修改其條件,保留乙個元素空間:

設佇列的最大尺寸為queuesize,佇列滿的條件是(rear+1)% queuesize == front(取模「%」的目的就是為了整合rear與front大小為乙個問題)。

通用的計算佇列長度公式為:

(rear - front + queuesize) % queuesize

4.迴圈佇列操作(佇列的順序儲存結構):

迴圈佇列的順序儲存結構**如下:

typedef int qelemtype; /*qelemtype型別根據實際情況而定,這裡假設為int*/

/*迴圈佇列的順序儲存結構*/

typedef struct

sqqueue;

迴圈佇列的初始化**如下:

/*初始化乙個空佇列q*/

status initqueue(sqqueue *q)

迴圈佇列求佇列長度**如下:

/*返回q的元素個數,也就是佇列的當前長度*/

int queuelength(sqqueue q)

迴圈佇列的入佇列操作**如下:

/*若佇列未滿,則插入元素e為q新的隊尾元素*/

status enqueue(sqqueue *q, qelemtype e)

迴圈佇列的出佇列操作**如下:

/*若佇列不空,則刪除q中隊頭元素,用e返回其值*/

status dequeue(sqqueue *q, qelemtype *e)

5.佇列的鏈式儲存結構—-尾進頭出。

隊頭指標指向鏈佇列的頭結點。隊尾指標指向終端結點。空佇列時,front和rear都指向頭結點。

鏈佇列的結構為:

typedef int qelemtype; /*qelemtype型別根據實際情況而定,這裡假設為int*/

typedef struct qnode; /*結點結構*/

qnode, *queueptr;

typedef struct /*佇列的鍊錶結構*/

linkqueue;

6.佇列的鏈式儲存結構—-入隊與出隊操作:

入隊操作:其實就是在鍊錶尾部插入結點。

/*插入元素e為q的新的隊尾元素*/

status enqueue(linkqueue *q, qelemtype e)

出隊操作:就是頭結點的後繼結點出隊,將頭結點的後繼改為它後面的結點,若煉表除頭結點外只剩乙個元素時,則需將rear指向頭結點。

/*若佇列不空,刪除q的隊頭元素,用e返回其值,並返回ok,否則返回error*/

status dequeue(linkqueue *q, qelemtype *e)

*迴圈佇列與鏈佇列比較:

時間上:時間複雜度都為o(1);

空間上:迴圈佇列需要事先申請好空間,使用期間不釋放,在空間上,鏈佇列更加靈活。

*建議:在可以確定佇列長度最大值的情況下,建議用迴圈佇列,如果無法預估佇列的長度時,則用鏈佇列。

#總結:棧分為順序棧和鏈棧,其中順序棧可以通過使用「兩棧共享空間」的方法解決順序棧的弊端;

佇列分為順序佇列和鏈佇列,其中順序佇列可以通過使用「迴圈佇列」的方法解決順序佇列的弊端。

資料結構學習筆記 線性表

線性表是零個或多個資料元素的有限序列。線性表的資料物件集合為。其中,除第乙個元素a1外,每乙個元素有且只有乙個直接前驅元素,除了最後乙個元素an外,每個元素有且只有乙個直接後繼元素。資料元素之間的關係是一對一的關係 線性表的順序儲存結構指的是用一段位址連續的儲存單元依次儲存線性表的資料元素。簡單的說...

資料結構學習之特殊線性表 佇列

順序基本定義 typedef 100 maxsize typedef int elemtype elemtype item maxsize int front int rear 結構定義 define maxsize 100 typedef int elemtype struct qnode str...

資料結構學習 線性表

線性表一般分為順序結構和鏈式結構。順序表裡面元素的位址是連續的,如陣列 鍊錶裡面節點的位址不是連續的,是通過指標連起來的,如單鏈表 順序結構 優點 易於查詢,索引快 list n 這樣的操作,o 1 複雜度。缺點 擴充套件性弱,不易刪除 插入,這兩項操作均是o n 的時間複雜度 鍊錶結構 優點 擴充...