【資料結構與演算法】 棧——棧的應用舉例(3例)
根據“後進先出”特性,生活中的例子比比皆是。
1數制轉換
假設要講十進位制轉換為二進位制。以 52 為例,如圖:
在上述計算過程中,第一次求出的X值為最低位,最後一次求出的X值為最高位。而列印時應從高位到低位進行,恰好與計算過程相反。根據這個特點,我們可以通過入棧出棧來實現,即將計算過程中依次得到的二進位制數碼按順序進棧,計算結束後,再順序出棧,並按出棧順序列印輸出。即可得到給定的二進位制數。這是利用棧後進先出特性的最簡單例子。
void Conversion(int N){ /*對於任意的一個非負十進位制數N,打印出與其對應的二進位制數*/ Stack S; int x; InitStack(&S); while (N>0) { x=N%2; Push(&S,x); //將餘數壓入棧S N=N/2; } while (!IsEmpty(&S)) { Pop(&S,&X); printf("%d",x); } }
2括號匹配問題
假設表示式有三種括號:圓括號“()”,花括號“{}”,方括號“[]”。它們可互相巢狀,如{([])}或{([])()[]}均為正確格式。而{)),{[()]均為不正確格式。如何檢測其正確性?可以應用棧。
我們以“{[()]}”為例,依次讀取括號,如圖:
注意,上面寫的雙雙出棧其實是,左括號出棧。
void BrackerMatch(char *str){ Stack S; int i; char ch; InitStack(&S); for (i=0;str[i]!='/0';i++) { switch (str[i]) { case '(': case '[': case '{': Push(&S,str[i]); break; case ']': case '}': case ')': if (IsEmpty(&S)) { printf("\n 右括號多餘!"); return; }else{ GetTop(&S,&ch); if(Match(ch,str[i])) //用 Match 判斷兩個括號是否匹配 Pop(&S,&ch); //已匹配的左括號出棧 else{ printf("\n對應的左右括號不同類"); return; } } default: break; } if (IsEmpty(&S)) printf("\n括號匹配!"); else printf("\n左括號多餘!"); } }
3表示式求值
表示式求值是高階語言編譯中的一個基本問題,是棧的典型應用例項。
1+2*3/(1+5)=2
任何一個表示式都是由數(運算元)和符號(運算子+-*/,界限符())組成。
而符號又有優先順序,優先計算得到的值再作為數繼續運算,當符號用盡後,值即為所得。
1+2*3/(1+5) --> 1+6/(1+5) --> 1+6/6 --> 1+1 --> 2
優先順序規則:
(1)先左後右
(2)先乘除,後加減
(3)先括號內,後括號外
此時需要兩個棧,一個稱作operator,用以存放符號。一個稱作operand,用於存放運算元或中間結果。下圖,為即將要用到的算符之間的優先關係。
演算法的基本過程如下:
初始化兩個棧,然後講表示式起始符“#”壓入operator棧。
輸入表示式,以“#”結尾。
依次讀取表示式,讀取過程中,若是運算元,直接入棧operand。若是符號,則與operator棧頂運算子進行比較。
(1)若 棧頂符<剛讀運算子 : 剛讀運算子 進棧;
(2)若 棧頂符>剛讀運算子 : 進行計算,operator棧頂符退棧,送入x,同時將operand棧退棧兩次,得到a,b,對a,b,x進行運算後,將結果作為中間結果推入operand棧;
(3)若 棧頂符=剛讀運算子 : 說明是左右括號相遇,棧頂符退棧即可;
當operator棧的棧頂符和當前符都為“#”時,說明求值完畢。
以(10+2)*3# 為例,如圖:
當棧頂符和當前符都是“#”,計算結束
int ExpEvaluation(){
/*operator為符棧,operand為數棧,OPS為運算子集合*/
InitStack(&operand);
InitStack(&operator);
Push(&operator,'#');
printf("\n輸入一個表示式(以#結束)");
ch=getchar();
while(ch!='#'||GetTop(operator)!='#'){ //GetTop 取棧頂
if (!In(ch,OPS)) { //不是操作符,是運算元
int temp;
temp=ch-'0'; //數的臨時變數,並轉換為十進位制
ch=getchar();
while (!In(ch,OPS)) { //數可能不只有一位,如100就要讀三次
temp=temp+10+ch-'0';
ch=getchar();
}
Push(&operand,temp);
}
else
switch (Compare(GetTop(operator),ch)) {
case '<':
Push(&operator,ch);
ch=getchar();
break;
case '=':
Pop(&operator,&x);
ch=getchar();
break;
case '>':
Pop(&operator,&op);
Pop(&operand,&b);
Pop(&operand,&a);
v=Execute(a,op,b); //對a和b進行op運算
Push(&operand,v); //注意這裡沒有 ch=getchar()
break;
}
}
v=GetTop(&operand);
return v;
}
以上均為學習耿國華的《資料結構-c語言》筆記