棧(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...