棧(stack)的應用

2022-08-09 08:39:08 字數 3565 閱讀 8050

棧(stack)通常也被稱之為「堆疊」。它的本質是線性表。堆(heap)通常我們也稱它為優先佇列,本質是樹。此處講述一些stack的應用。

編譯器在檢查(){}這樣成對出現的符號所造成的語法錯誤時,通常並不需要去設計乙個很複雜的程式去判斷。而是使用乙個簡單的演算法,這個演算法用到乙個棧。演算法描述如下:

做乙個空棧,從這串**的開始讀到末尾。如果讀到的字元是乙個開放字元——左括號,那麼將它入棧。如果是乙個封閉符號——右括號,這時將棧中的元素彈出。如果彈出的元素是封閉符號對應的開放符號,那麼正確(正確的時候不做任何提示),否則就報錯。如果這時的棧為空,那麼說明缺失了開放字元,報錯。當這串**讀完時,如果棧不為空,那麼報錯。

下面給出其c語言實現的**:棧及其實現不表

int issyntaxerror(const char *p,const int num)

if(')' == *p)

}if('}' == *p)

}} if(!stackisempty())

return error;

}

中綴表示式:操作符位於運算元中間,例如:2+3*5。我們現在使用的算術表示式就是中綴表示式。

字尾表示式:操作符放在兩個運算元的後面,並且嚴格遵守從左向右的運算規則。而且字尾表示式相比於字首表示式是沒有括號運算子的。例如:2 3 *(對應的中綴表示式就是2*3)。

字首表示式:與字尾表示式剛好相反,操作符位於兩個運算元之前。

字首表示式我們也常稱為「波蘭表示式」,字尾表示式常稱為「逆波蘭表示式」。

下面是將中綴表示式轉換成字尾表示式的一般步驟:假設我們從標準輸入讀取乙個中綴表示式

讀到乙個數字時,立即將數字放入輸出流。

讀到左括號時,將其壓入堆疊中。

遇到右括號時,右括號本身不入棧,從棧頂開始彈出操作符,放入輸出流,直到遇到乙個左括號為止,將這個左括號彈出,但是不放入輸出流。

遇到運算子時,若該運算子的優先順序高於當前棧頂運算子的優先順序,則將它壓入棧,若該運算子的優先順序小於等於當前棧頂運算子的優先順序,將棧頂運算子彈出到輸出流,然後按照規則繼續與新的棧頂運算子進行比較,直到運算子優先順序大於棧頂運算子的優先順序,將運算子壓入棧。

按照以上步驟將表示式處理完後,此時若堆疊不為空,則將棧中所有運算子彈出到輸出流。

需要注意的是,左括號的優先順序的問題,它在棧外時,優先順序最高,在棧內時優先順序最低。因此必須處理好左括號的優先順序。我的**只是實現了轉換,但是實現的並不怎麼好。下面給出**。

#ifndef stack

#define stack

#include#includetypedef struct stacknode stack;

typedef stack * psnode;

struct stacknode

;psnode creatstack();

int isempty(psnode s);

void push(psnode s,char c);

char pop(psnode s);

#endif // !stack

#include "stack.h"

psnode creatstack()

int isempty(psnode s)

else }

void push(psnode s,char c)

char pop(psnode s)

else

}

#include"stack.h"

#define max 100

void transform(char *ch); //轉換函式

psnode s1;

int main()

void transform(char * ch)

//將字串轉換成整數(**不支援浮點數)

if ('0' <= ch[i] && '9' >= ch[i])

}else

if (!isempty(s1) && ')' == ch[i]) //遇到右括號且棧不空

if (isempty(s1))

else

}if ('+' == ch[i]) //遇到加號

else

push(s1, ch[i]);}}

if ('-' == ch[i]) //遇到減號

else

push(s1, ch[i]);}}

if ('*' == ch[i]) //遇到乘號

else

push(s1, ch[i]);}}

if ('/' == ch[i]) //遇到除號

else

push(s1, ch[i]);}}

if ('(' == ch[i] ) //遇到左括號

}} while (!isempty(s1)) //讀入結束後,棧不空就將棧中所有運算子彈出

}

當遇到運算元時,直接壓入棧中。

遇見操作符時,就從棧中彈出兩個運算元,把這兩個運算元按照操作符的運算規則進行運算,將運算結果也壓入棧中。

重複以上兩個步驟,直到將表示式計算完畢。

#include"stack.h"

elementtype calc(pstack s, char *str);

int main()

printf("錯誤,表示式運算子數目過少!按任意鍵結束...");

getchar();

exit(0);

} printf("計算結果是:%d\n", data);

system("pause");

return 0;

}elementtype calc(pstack s, char * str)

if ('0' <= str[i] && '9' >= str[i]) //將數字入棧

continue;

} if (' ' == str[i])

if (' ' != str[i])

switch (str[i])

case '-':

case '*':

case '/':

default:

}} }

return s->next->data; //返回計算結果

}

在這段**的棧實現中,稍微更改了pop()函式。將修改後的pop函式放在下面.

elementtype pop(pstack s)

else

}

結合上面的中綴表示式轉字尾表示式,以及字尾表示式求值。我們可以得到計算乙個中綴表示式的方案。當然了,在中綴表示式轉字尾表示式的過程中就可以邊轉邊計算。(這樣的演算法是聯機的)

當呼叫乙個函式時,主調程式的所有區域性變數都需要儲存起來,否則被呼叫的新函式將會覆蓋呼叫例程的變數。當然,還需要將主調程式的當前位置必須儲存,這樣當被調函式執行完後,才能返回到原來的地方繼續執行。這些都可以用棧來方便的實現。對於遞迴函式而言,遞迴總是能夠被去除的(編譯器完成這個操作),這樣需要借助乙個棧。去除遞迴可能會使程式的執行速度變快,但是也會使的程式的簡明性下降。

棧Stack的實現及其應用

棧 先進後出 實現方式有兩種,一種使用陣列,一種是鏈式結構 使用陣列的缺點就是在定義棧的時候就需要以某值初始化陣列,確定陣列的大小,也就是確定了棧的深度 棧 底層用陣列實現 public class arrstack 陣列滿的時候棧滿 public boolean isfull 棧空時top為 1 ...

棧 Stack 的理解及其應用

棧的抽象資料型別 棧的抽象資料型別由以下結構和操作定義 棧被構造為項的有序集合,其中項被新增和從末端移除的位置稱為 頂部 棧是有序的 lifo 棧操作如下 簡單來說,類似於放一摞書,最先放的書在最下面,因此最後放的書最先取出來,而最後取出放的第一本書,棧就是這樣一種資料結構。我們可以用python的...

棧(stack) 什麼是棧?

1.棧是一種特殊的線性結構 棧滿足線性結構 棧特殊性 棧有特殊的儲存方式,訪問結構 先進先出,進和出在乙個端 2.棧的操作 入棧 向棧口放入資料元素 push 出棧 從棧口取出資料元素 pop 棧頂指標 top 用來指向最後乙個入棧元素 入棧操作 設棧的最大長度為size,棧滿不可入棧 上溢 top...