資料結構學習筆記5(棧)

2021-06-20 12:37:01 字數 2921 閱讀 5194

在學習組合語言時候曾經簡要接觸過棧。棧可能是繼陣列之後在技術安吉科學中最基本的資料結構。基本思想是先進先出,可以看做是乙個桶。最先進入的最後出,最後進的最先出。

棧可以用鍊錶或者陣列實現。

陣列實現的缺點在於需要提前預知棧的大小,並定義出來;但是,一般在應用程式中,即使有相當多的棧操作,在任意時刻站元素的實際個數也不會太大。

鍊錶可以節省潛在的空間,但是鍊錶實現需要空間定義指標,並且消耗時間來malloc和free操作。

兩種實現方法原理相同,不過鍊錶實現稍顯麻煩。這裡給出陣列的實現方法。

棧有乙個topofstack,對於空棧它是-1,相當於棧的初始化。push x就是講topofstack加1,然後stack[topofstack]=x,stack代表具體的陣列。pop x就是返回stack[topofstack],然後topofstack減1。(stack就是乙個陣列,只不過人為操作使得stack有了「棧」這個洋氣的名字)。

影響棧的執行效率的問題是錯誤檢測

。如對空棧的pop和對滿棧push都會超出陣列界限。但是對這些條件的檢測在陣列實現過程中可能花費實際棧操作的時間。所以除非處理及重要的場合(如os),一般棧例程中省去錯誤檢測。棧操作幾乎花費常數時間,程式的執行時間也不集中於此。在應用程式中,應該隨時編寫錯誤檢測的**。

#include #include #include #include "stack_h.h"

struct stackrecord

;#define emptytos -1 //沒有; ,語法小錯害人不淺啊

#define minstacksize 5

//creat a new stack

stack creatstack(int maxelements)

int isempty(stack s)

int isfull(stack s)

void disposestack(stack s)

}void makeempty(stack s)

void push(stack s,elementtype x)

elementtype top(stack s)

return s->array[s->topofstack];//只返回,不彈出

}void pop(stack s)

*/ s->topofstack--;

}elementtype popandtop(stack s)

*/ return s->array[s->topofstack--];//返回;棧s的座標改變

}

現在程式設計vc++6.0和vs都有自動檢測功能,但是我們可以自己寫乙個程式來檢查自己的程式檔案在小的語法錯誤比如(){}配對上是否正確無誤。

基本思想是:設定乙個陣列棧,大小可以定為10;讀入程式檔案(這個可以參考k&r的《c程式語言》),然後對遇到的所有 就對棧裡的字元popandtop進行比較,如果配對那麼對檔案接著往下遍歷,如果不配對,程式設計就錯了。如果碰到  )  ]   } 時候棧空,報錯;如果讀到檔案結尾時,棧非空,報錯。

貌似這個比較厲害?

字首、字尾表示式是中綴表示式的一種變形,其中如果中綴表示式是a+b*c+(d*e+f)/g那麼字尾表示式就是abc*+de*f+g/+。易知,中綴表示式是常用的表示式,字尾表示式則顯得比較「怪異」,但是可以看到字尾表示式中沒有()這種運算子。但是,計算機時按照字尾表示式來進行計算的(字首表示式是從右向左掃瞄,不常用)。

中綴到字尾轉換幾條守則:1讀到乙個運算元時,輸出;讀到 + - * / ( 操作符時放入棧中;2讀到 ) 時彈出棧中的元素並輸出直到彈出(,兩個符號都不輸出;3遇到除 ( 以外的運算子則比較棧頂運算子的優先順序 * />+ -,如果棧中運算子的等級高於或等於該運算子,則彈出棧中的運算子並將,如遇到+則彈出/ * - +並將 + 入棧。除非遇到 ) ,否則不從棧中移走 ( 。4在讀到輸入的末尾,將佔元素彈出知道該棧變空。

如a+b*c+(d*e+f)/g表示式,

a輸出  +入棧  b輸出  *入棧  c輸出(此時棧中是+*,輸出是ab),遇到+優先順序最低,輸出 * +,即abc*+,此時棧中還有乙個剛剛入棧的+;

然後 ( 入棧  d輸出   *入棧  e輸出  ,遇到+,*輸出+入棧,此時輸出是abc*+de*,棧中是+(+;

然後 f 輸出 ,遇到 ) ,+ 輸出,()消去,則輸出是abc*+de*f

+,棧中是+;

然後/入棧,g輸出,到結尾,/+依次輸出,即為abc*+de*f+g/+

字尾表示式轉中綴表示式,見到乙個數把它入棧,遇到乙個運算法則彈出兩個數進行計算並將計算結果入棧。如6523+8*+3+*就是6523入棧,遇到+計算2+3得到5入棧655,8入棧遇到*則8*5得40入棧6 5 40遇到+得6 45,3入棧遇+得6 48遇*得6*48=288。可以手工寫出計算式為((2+3)*8+5+3)*6 

int main(void)

else

}} while(s->topofstack!=-1)

putchar(popandtop(s));

return 0;

}

這裡的問題在於如何識別字尾表示式中的數字是個位數還是乙個大於10的數。字尾表示式如果用字串表示,那麼就不存在大於10的數。也可以在字串中加入特殊的符號來說明此處是乙個三位數etc.,但是鑑於目的不在此,就利用書上例子6523+8*+3+*來寫出實現計算的**。

...

這一部分主要意思是講在函式呼叫中,原來的區域性變數和呼叫函式的位址等活動記錄需要存起來。存**呢?棧(stack)。但是如果棧太大,可能與程式覆蓋,可能存在沖毀棧的風險,程式奔潰。

失控遞迴(通常是忘記基準情形)會躍出棧空間。另外,當使用巢狀很多的遞迴時,會存在這個風險。因為每乙個遞迴呼叫的活動記錄都要存起來。

如果是尾遞迴(在程式最後一行使用遞迴),系統將自動轉換為goto語句並在其前加上對函式每個引數的賦值語句。

資料結構學習筆記 棧

它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。這一端被稱為棧頂,相對地,把另一端稱為棧底。向乙個棧插入新元素又稱作進棧 入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成為新的棧頂元素 從乙個棧刪除元素又稱作出棧或退棧,它是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素。p...

資料結構學習筆記 棧

1.定義 棧 stack 是限定僅在表尾進行插入和刪除操作的線性表。根據定義我們知道棧在本質上也是一種線性表,只是在插入和刪除操作上進行了限制。我們把允許插入和刪除的一端稱為棧頂 top 另一端稱為棧底 bottom 不含任何元素的棧稱為空棧。棧又稱為後進先出 last in first out 的...

資料結構學習記錄5 棧(順序棧)

三.實現 棧是一種僅在表尾進行插入或者刪除操作的線性表。且表的首尾兩端都有特殊的含義 表頭我們一般稱為棧底,表尾 最後乙個元素的位置 稱為棧頂,不含元素或者棧底 棧頂的棧,我們稱之為空棧。所以,棧是一種先進後出的表結構。這種情況,和我們的火車排程站非常相似。因為棧的內部儲存結構,可以用順序結構,也可...