棧的應用1--遞歸
把一個直接調用自己或通過一系列的調用語句間接地調用自己的函數,稱做遞歸函數。
寫遞歸最怕的就是陷入永不結束的無窮遞歸中,所以,每個遞歸定義必須至少有一個條件,滿足時遞歸不再進行,即不再引用自身而是返回值退出。
迭代和遞歸的區別是:迭代使用的是循環結構,遞歸使用的是選擇結構。遞歸能是程序的結構更清晰,更簡潔,更容易讓人容易理解,從而減少讀懂代碼的時間。但是大量的遞歸調用會建立函數的副本,會大量消耗時間和內存。迭代則不需要反覆調用函數和佔用額外的內存。
用常規的迭代方法打印前40位的斐波那契數數列:
int main()
{
int i;
int a[40];
a[0] = 0;
a[1] = 1;
printf("%d ", a[0]);
printf("%d ", a[1]);
for (i = 2; i < 40; i++)
{
a[i] = a[i -1] + a[i - 2];
printf("%d ", a[i]);
}
return 0;
}
用遞歸方法實現:
int Fbi(int i)
{
if (i < 2)
return i == 0 ? 0 : 1;
return Fbi(i - 1) + Fbi(i - 2);
}
int main()
{
int i;
for (i = 0; i < 40; i++)
printf("%d ", Fbi(i));
return 0;
}
棧與遞歸的關係:
在程序的前行階段,對於每一層遞歸,函數的局部變量、參數值以及返回地址都被壓入棧中。在退回階段,位於棧頂的局部變量、參數值和返回地址被彈出,用於返回調用層次中執行代碼的其餘部分,也就是恢復了調用的狀態。
棧的應用2--四則運算表達式求值
1、將中綴表達式轉化爲後綴表達式
我們平時使用的四則運算表達式,叫做中綴表達式,如:9 + (3 - 1) × 3 + 10 ÷ 2
中綴表達式“9 + (3 - 1) × 3 + 10 ÷ 2”轉化爲後綴表達式“9 3 1 - 3 * + 10 2 / +”
規則:從左到右遍歷中綴表達式的每個數字和符號,若是數字則輸出,即成爲後綴表達式的一部分;若是符號,則判斷其與棧頂符號的優先級,是右括號或優先級不高於棧頂符號(乘除優先加減)則棧頂元素依次出棧並輸出,並將當前符號進棧,一直到最終輸出後綴表達式爲止。
2、將後綴表達式進行運算得出結果
規則:從左到右遍歷表達式的每個數字和符號,遇到所數字就進棧,遇到符號就將處於棧頂的兩個數字出棧,進行運算,運算結果進棧,一直到最終獲得結果。