習題部分
選擇題
第一題
一個問題的遞歸算法求解和其相對應的非遞歸算法求解()
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>
的優先級來進行棧的變化,我們用icp來表示當前掃描到的運算符ch的優先級,該運算符進棧後的優先級爲isp,則運算符的優先級如下表所示:
(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/+
後綴式子出現
當題目要求直接求前綴或後綴表達式時,這種方法會比上一中快捷的多。