堆疊(Stack)作為「後進先出」(LIFO)的核心資料結構,是解決許多經典計算機科學問題的利器。本文系統梳理三大堆疊經典應用——括號匹配、後綴表達式求值、中綴轉後綴表達式——並附上完整 C 語言實作碼,助你徹底掌握堆疊演算法精髓。
( [ { → 入堆疊。) ] } →
( 對 ])→ 匹配失敗。int match(char *cs, int size) {
Stack s = CreateStack(size);
for (int i = 0; i < size; i++) {
char ch = cs[i];
if (left(ch)) Push(ch, s);
else if (right(ch))
if (IsEmpty(s) || !pair(TopAndPop(s), ch)) return FALSE;
}
return IsEmpty(s) ? TRUE : FALSE;
}
輔助函式 left()、right()、pair() 封裝了判斷邏輯,使主流程清晰易讀。
假設輸入為合法後綴表達式(逆波蘭表示法),運算元為個位數字:
isdigit())→ 轉為整數 入堆疊。+ - * / → 彈出兩個運算元(注意順序:第二個彈出的是左運算元),計算結果 入堆疊。case '-':
tmp = TopAndPop(s); // 右運算元
Push(tmp - TopAndPop(s), s); // 左運算元 - 右運算元
break;
case '/':
tmp = TopAndPop(s);
Push(tmp / TopAndPop(s), s); // 左運算元 / 右運算元
break;
減法與除法順序敏感,必須用暫存變數保證正確順序,這是初學者常犯錯誤的地方。
+ - * / →
( → 直接 入堆疊(優先級最低,作為邊界)。) → 彈出並輸出堆疊元素,直到遇到 ( 為止(( 僅彈出不輸出)。static int compareSymbol(char symbol, char prevSymbol) {
if (prevSymbol == '(') return 1; // 當前優先級高於 '('
if (symbol == '+' || symbol == '-') {
return (prevSymbol == '+' || prevSymbol == '-') ? 0 : -1;
} else { // * /
return (prevSymbol == '+' || prevSymbol == '-') ? 1 : 0;
}
}
返回值約定:1 當前優先級較高,0 相等,-1 較低。此設計巧妙處理了括號與同優先級運算元的左結合性。
int main() {
// 1. 括號匹配測試
char chars[] = "1 + {5 * [4 - (4 - 10) + 2 * 23] + 12 / 11}(";
puts(match(chars, strlen(chars)) ? "true" : "false"); // false (多一個 '(')
// 2. 後綴求值測試: 6 5 2 3 + 8 * + 3 + * => 6 * (5 + (2+3)*8 + 3) = 6 * (5+40+3) = 288
char exp1[] = "6523+8*+3+*";
printf("postfixValue=%d\n", postfixValue(exp1, strlen(exp1))); // 288
// 3. 中綴轉後綴測試: a+b*c+(d*e+f)*g => a b c * + d e * f + g * +
char exp2[] = "a+b*c+(d*e+f)*g";
convertExpression(exp2, strlen(exp2)); // 輸出: a b c * + d e * f + g * +
return 0;
}
這三大演算法展示了堆疊「暫存與反轉」的核心威力:
掌握這些模式,不僅能應付面試考題,更能深入理解編譯器、解析器、虛擬機等系統軟體的基石邏輯。