棧和佇列的應用相關習題及詳解 ——資料結構
習題部分
選擇題
第一題
一個問題的遞迴演算法求解和其相對應的非遞迴演算法求解()
A. 遞迴演算法通常高效一些 B. 非遞迴演算法通常高效一些
C. 兩者相同 D. 無法比較
第二題
執行()操作時,需要使用佇列作為輔助儲存空間
A. 查詢雜湊(雜湊)表 B. 廣度優先搜尋圖
C. 前序(根)遍歷二叉樹 D. 深度優先搜尋圖
第三題
已知操作符包括‘+’‘-’‘’‘/’‘(’‘)’ 。將中綴表示式a+b-a((c+d)/e-f)+g轉化為等價的字尾表示式ab+acd+e/f-*-g+時,用棧來存放暫時還不能確定運算次序的操作符。若棧初始時為空,則轉換過程中同事儲存在棧中的操作符的最大個數是()
A. 5 B. 7
C. 8 D. 11
第四題
假設棧初始為空,將中綴表示式a/b+(c*d-e*f)/g轉化為等價的狗追表示式的過程中,當掃描到f時,棧中的元素依次是()
A. +(*- B. +(-* C. /+(*-* D. /+-*
解答部分
第一題
通常情況下,遞迴演算法在計算機實際執行的過程中包含很多的重複計算,所以效率會低
第二題
圖的廣度優先搜尋類似於樹的層序遍歷,同樣需要藉助於佇列
第三題
考察棧在種豬表示式轉化為字尾表示式中的應用。
將中綴表示式a+b-a*((c+d)/e-f)+g轉換為相應的字尾表示式,需要根據操作符<op>
(isp)是棧內優先(in stack priority)數,icp是棧外優先(in coming priority)數。
操作符 | # | ( | *,/ | +,- | ) |
---|---|---|---|---|---|
isp | 0 | 1 | 5 | 3 | 6 |
icp | 0 | 6 | 4 | 2 | 1 |
我們在表示式後面加上‘#’,表示表示式結束,具體換換過程如下:
步驟 | 掃描項 | 項型別 | 動作 | 棧內內容 | 輸出 |
---|---|---|---|---|---|
isp | 0 | 1 | 5 | 3 | 6 |
icp | 0 | 6 | 4 | 2 | 1 |
0 | #進棧,讀下一符號 | # | |||
1 | a | 運算元 | 直接輸出 | # | a |
2 | + | 操作符 | isp(‘#’) < icp(‘+’),進棧 | #+ | |
3 | b | 運算元 | 直接輸出 | #+ | b |
4 | - | 操作符 | isp(‘+’) > icp(‘-‘),退棧並輸出 | # | + |
5 | isp(‘#’) < icp(‘-‘),進棧 | #- | |||
6 | a | 運算元 | 直接輸出 | #- | a |
7 | * | 操作符 | isp(‘-‘) < icp(‘*’)進棧 | #-* | |
8 | ( | 操作符 | isp(‘*’) < icp(‘(‘),進棧 | #-*( | |
9 | ( | 操作符 | isp(‘(‘) < icp(‘(‘),進棧 | #-*(( | |
10 | c | 運算元 | 直接輸出 | #-*(( | c |
11 | + | 操作符 | isp(‘(‘) < icp(‘+’),進棧 | #-*((+ | |
12 | d | 運算元 | 直接輸出 | #-*((+ | d |
13 | ) | 操作符 | isp(‘+’) > icp(‘)’),退棧並輸出 | #-*(( | + |
14 | isp(‘(‘) == icp(‘)’),直接退棧 | #-*( | |||
15 | / | 操作符 | isp(‘(‘) < icp(‘/’),進棧 | #-*(/ | |
16 | e | 運算元 | 直接輸出 | #-*(/ | e |
17 | - | 操作符 | isp(‘/’) > icp(‘-‘),退棧並輸出 | #-*( | / |
18 | isp(‘(‘) < icp(‘-‘),進棧 | #-*(- | |||
19 | f | 運算元 | 直接輸出 | #-*(- | f |
20 | ) | 操作符 | isp(‘-‘) > icp(‘)’),退棧並輸出 | #-*( | - |
21 | isp(‘(‘) == icp(‘)’),直接退棧 | #-* | |||
22 | + | 操作符 | isp(‘*’) > icp(‘+’),退棧並輸出 | #- | * |
23 | isp(‘-‘) > icp(‘+’),退棧並輸出 | # | - | ||
24 | isp(‘#’) < icp(‘+’),進棧 | #+ | |||
25 | g | 運算元 | 直接輸出 | #+ | g |
26 | # | 操作符 | isp(‘+’) > icp(‘#’),退棧並輸出 | # | |
27 | isp(‘#’) == icp(‘#’),退棧,結束 |
第四題
將中綴表示式轉換字尾表示式的演算法思想如下:
從左向右開始掃描中綴表示式;
遇到數字時,加入字尾表示式;
遇到運算子時:
a.若為‘(’,入棧;
b.若為‘)’,則一次把棧中的運算子加入字尾表示式中,直到出現‘(’,從棧中刪除‘(’;
c.若為除括號外的其他運算子,當其優先順序高於除‘(’意外的棧頂運算子時,直接入棧。否則從棧頂開始,一次彈出比當前處理的運算子優先順序高和優先順序相等的運算子,直到一個比它優先順序低的或者遇到了一個左括號位置。
當掃描的中綴表示式結束時,棧中的所有運算子一次出棧加入字尾表示式。
待處理序列 | 棧 | 字尾表示式 | 當前掃描元素 | 動作 |
---|---|---|---|---|
a/b+(c*d-e*f)/g | a | a加入字尾表示式 | ||
/b+(c*d-e*f)/g | a | / | /入棧 | |
b+(c*d-e*f)/g | / | a | b | b加入字尾表示式 |
+(c*d-e*f)/g | / | ab | + | +優先順序低於棧頂的/,彈出/ |
+(c*d-e*f)/g | ab/ | + | +入棧 | |
(c*d-e*f)/g | + | ab/ | ( | (入棧 |
c*d-e*f)/g | +( | ab/ | c | c加入字尾表示式 |
*d-e*f)/g | +( | ab/c | * | 棧頂為(,*入棧 |
d-e*f)/g | +(* | ab/c | d | d加入字尾表示式 |
-e*f)/g | +(* | ab/cd | - | -優先順序低於棧頂的,彈出 |
-e*f)/g | +( | ab/cd* | - | 棧頂為(,-入棧 |
e*f)/g | +(- | ab/cd* | e | e加入字尾表示式 |
*f)/g | +(- | ab/cd*e | * | *優先順序高於棧頂的-,*入棧 |
f)/g | +(-* | ab/cd*e | f | f加入字尾表示式 |
)/g | +(-* | ab/cd*ef | ) | 把棧中(之前的符號加入表示式 |
/g | + | ab/cd*ef*- | / | /優先順序高於棧頂的+,/入棧 |
g | +/ | ab/cd*ef*- | g | g加入字尾表示式 |
+/ | ab/cd*ef*-g | 掃描完畢,運算子一次退棧加入表示式 | ||
ab/cd*ef*-g/+ | 完成 |
由此可知,當掃描到f的時候,棧中的元素一次是+(-*
,選B。
再次再給出中綴表示式轉換為字首或字尾表示式的手工做法,以上面給出的中綴表示式為例:
第一步:按照運算子的優先順序對所有的運算單位加括號
式子變成了:((a/b)+(((c*d)-(e*f)/g))
第二部:轉換為字首或字尾表示式。
字首:把運算子號移動到對應的括號前面,則變成了:+(/(ab)/(-(*(cd)*(ef))g))
把括號去掉:+/ab/-*cd*efg
字首式子出現
字尾:把運算子移動到對應的括號 後面,則變成了:((ab)/(((cd)*(ef)*)-g/)+
把括號去掉:ab/cd*ef*-g/+
字尾式子出現
當題目要求直接求字首或字尾表示式時,這種方法會比上一中快捷的多。