114 年 國立中山大學電機工程學系碩士班丙組《資料結構》
第 1 題30 分
【此題30分;每小題15分】
①下圖為一個AVL tree,每個node 裡頭的數字代表一筆資料的key值;root的key值為49。
畫出「刪除 key 值為49 的資料」之後的AVL tree。
②承上題,在「刪除key值為49的資料」之後,接著畫出「插入key 值為35的資料」之後
所產生的AVL tree。
49
31
74
19
38
66
79
24
57
69
83
72
登入後即可作答並保存紀錄。
核心觀念
AVL 樹是二元搜尋樹,且每個節點的左右子樹高度差最多為 。平衡因子定義為:
刪除節點或插入節點後,若有節點的平衡因子超出 到 ,就須以旋轉恢復平衡。
題目未指定刪除有兩個子節點的節點時,要採用中序前驅或中序後繼。以下採常用的中序後繼規則:以右子樹中最小的鍵值取代被刪除的鍵值。
解題方法
① 刪除根節點 :
有兩個子節點,其中序後繼是右子樹中最小的鍵值 。以 取代 ,再從原位置刪除 。此時節點 的左子樹為空,右子樹為 (其右子節點為 ),所以:
這是右右型失衡,在 處做一次左旋,得到以 為根、左右子節點分別為 與 的子樹。旋轉後,節點 與根節點 都符合 AVL 平衡條件。
刪除後的 AVL 樹:
第 2 題15 分
【此題15分】給定一個陣列A,裡頭包含n個互不相同的整數元素,分別儲存在A[0]至
A[n-1]。寫一個遞迴函式(recursive function),函式名稱為find_max,能在O(n)的時間
內找出陣列A裡頭的最大元素。若你所寫的find_max 函式不為遞迴函式,此題將不給分。
登入後即可作答並保存紀錄。
核心觀念
本題考查「遞迴」與「線性搜尋」:
- 陣列最大值的定義:
- 將問題縮小為:
- 找出 至 的最大值。
- 再將它與 比較。
- 必須設定基底條件,避免遞迴無限進行。
- 每個元素只被比較有限次,因此時間複雜度可達 。
題目給定 個元素,假設 。
解題方法
令 find_max(A, n) 表示找出陣列中前 個元素的最大值。
當 時,陣列只有 ,最大值就是 :
當 時,先遞迴找出 至 的最大值,再與 比較:
因此:
因為題目說所有元素互不相同,所以不會發生相等情況;即使允許重複元素,使用 或 也都能正確找出最大值。
關鍵程式碼
以下以 C 語言風格表示:
int find_max(int A[], int n) {
if (n == 1) {
return A[0];
}
int max_of_rest = find_max(A + 1, n - 1);
if (A[0] > max_of_rest) {
return A[0];
} else {
return max_of_rest;
}
}
呼叫方式:
int answer = find_max(A, n);
第 3 題15 分
【此題15分】給定一個陣列A,裡頭包含n個互不相同的整數元素。我們想用最少的 worst
case 執行時間在陣列A裡頭找出前k個最大的元素,其中k遠小於n,例如:k=100、
n = 2¹”。請問用 selection sort、heap sort、quick sort 這三種排序法裡頭的哪一種最合適?
先講答案,然後才針對這三種排序方法作分析。「沒有分析」或「分析錯誤」皆不給分。
登入後即可作答並保存紀錄。
【答案】使用 heap sort(以最大堆方式)最合適。
分析
-
Selection sort
- 只做 次選擇,每次遍歷整個陣列。
- 時間 。
- 時仍為線性倍增,對大 不具優勢。
-
Heap sort(建最大堆)
- 建堆:。
- 抽出最大值 次,每次 。
第 4 題15 分
【此題15分】請將下列後序式(postfix) 轉成前序式(prefix),其中A、B、C、D、E、F分別
代表6個互不相同的運算元 (operands)。註:必須寫出推導過程;直接寫答案,此題0分。
DB + FACE+/-*
登入後即可作答並保存紀錄。
推導過程
使用堆疊法,由左至右讀取 postfix,遇到運算元直接壓入堆疊,遇到運算子彈出兩個最近的元素,組成 prefix 子式再壓回。
| 讀入 | 堆疊內容(從底至頂) |
|---|---|
| D | D |
| B | D B |
| + | + D B |
| F | + D B F |
| A | + D B F A |
| C | + D B F A C |
第 5 題15 分
【此題15分】我們可以用 adjacent matrix 或 adjacency lists 的方式儲存 undirected graph。
給定 undirected graph G,假設G的 vertices數量為n,maximum degree為d,且d遠小於n。
我們想透過 breadth-first search的方式拜訪G裡頭所有的 vertices。那麼用 adjacent matrix 或
adjacency lists 哪一種方式儲存 undirected graph可以有較小的time complexity?先講答案,
然後才提出你的分析。「沒有分析」或「分析錯誤」皆不給分。
登入後即可作答並保存紀錄。
**先講答案:**應使用 adjacency lists(鄰接串列),其 BFS 的時間複雜度較小。
核心觀念
設圖 有:
- 個 vertices
- 條 edges
- maximum degree 為
BFS 的主要工作包含:
- 每個 vertex 至多被拜訪、加入佇列一次,成本為 。
- 對每個 vertex 掃描其所有鄰居,成本取決於圖的儲存方式。
對 undirected graph,由握手定理:
又因為每個 vertex 的 degree 不超過 :
解題方法與複雜度分析
一、使用 adjacency matrix
Adjacency matrix 是 的矩陣。當 BFS 拜訪某個 vertex 時,必須掃描矩陣中對應的整列,逐一確認 是否與其他 vertex 相鄰。
每個 vertex 都要掃描 個位置,而共有 個 vertices:
即使某個 vertex 的實際 degree 很小,仍然必須掃完整列,因此 maximum degree 很小也無法降低此方法的主要成本。
二、使用 adjacency lists
Adjacency lists 直接儲存每個 vertex 的鄰居。BFS 拜訪 vertex 時,只需掃描 的 adjacency list,不必檢查不存在的 edges。
所有 adjacency lists 的總長度為:
因此,所有鄰居總共只會被掃描 次,常數 不影響漸近複雜度:
第 6 題10 分
【此題10分】假設有n筆key值互不相同的資料,並且n的值很大。我們很在乎搜尋資料
的時間。那麼如何儲存這n筆資料,才能夠讓平均搜尋時間最小?先講答案,
然後才解說你的理由。
登入後即可作答並保存紀錄。
答案先講
在一般允許使用雜湊的前提下,應將資料儲存在**雜湊表(hash table)**中,使用分布均勻的雜湊函數,並控制負載因子,使平均搜尋時間達到 。這是漸近意義下的最佳結果。若 key 值域很小且連續,則可使用直接定址表(direct-address table),搜尋時間甚至可達到 的最壞情況。
核心觀念
這題考的是字典(dictionary)的搜尋效率,以及下列資料結構的時間複雜度:
- 未排序陣列或鏈結串列:平均 。
- 已排序陣列搭配二分搜尋:平均 。
- 平衡二元搜尋樹:平均 。
- 雜湊表:在雜湊函數良好、碰撞受控制時,平均 。
雜湊表使用雜湊函數 將 key 轉換成表格索引:
其中 是雜湊表的槽位數。若不同 key 對應到相同槽位,就會發生碰撞(collision)。
令負載因子為
只要維持 ,每個槽位平均只需處理常數數量的資料。
解題方法與推導
採用分離鏈結(separate chaining)處理碰撞。每個槽位存放一條鏈結串列,將所有具有相同雜湊值的資料放在同一串列中。
在簡單均勻雜湊(simple uniform hashing)的假設下:
- 不成功搜尋時,預期需要檢查的資料筆數約為
- 成功搜尋時,若每筆資料被搜尋的機率相同,平均檢查筆數約為