115 年 國立中山大學電機工程學系碩士班丙組《資料結構》
第 1 題30 分
【此題30分;每小題15分】
舉凡可以儲存大量資料的資料結構皆可稱為「容器(container)」,例:陣列(array) 就是一種
容器。假設陣列的容量(capacity)為n,裡頭有k<n個元素;當k變小時,搜尋元素的平均
時間就會減少。
(a) 然而,當我們用 open addressing 的方式實作 hash table時,卻可能發生裡頭的元素數量k
減少時,搜尋元素的平均時間未必減少,請問這是為什麼?請舉例解說。
(b) 請提出至少一種具體的方法來減緩上述問題。
登入後即可作答並保存紀錄。
核心觀念
在 open addressing 中,所有資料都直接放在 hash table 陣列內。發生碰撞時,必須依照 probe sequence 逐格尋找。例如 linear probing 使用:
搜尋時,遇到目標元素表示成功;遇到「從未使用過的空槽」才能判定元素不存在。
刪除資料時不能直接把槽位標成一般的 EMPTY,因為後續元素可能是經由碰撞探查到該位置之後才存放的。因此通常使用特殊標記 DELETED,也稱為 tombstone。搜尋遇到 DELETED 時必須繼續探查,插入時才可 reutilize 該槽位。
若目前有 個有效元素、 個 tombstone,則:
但搜尋實際感受到的探查負載接近:
所以, 變小並不代表搜尋一定變快;碰撞形成的 cluster、tombstone 數量,以及被刪除的是哪一個元素,都會影響平均搜尋時間。
(a) 為什麼 減少時平均搜尋時間未必減少
以容量 、雜湊函數
以及 linear probing 為例。依序插入 ,它們的初始雜湊位置全部是 :
| 索引 | 0 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|---|
| 內容 | 0 | 10 | 20 | 30 | 40 | EMPTY |
成功搜尋各元素所需探查次數如下:
| 元素 | 0 | 10 | 20 | 30 | 40 |
|---|---|---|---|---|---|
| 探查次數 | 1 | 2 | 3 | 4 | 5 |
因此平均搜尋次數為:
現在刪除元素 。若直接把索引 設為 EMPTY,搜尋 時會從索引 開始:
搜尋在索引 遇到空槽後就會誤判不存在,即使 實際位於索引 。
因此索引 必須標記為 DELETED:
| 索引 | 0 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|---|
| 內容 | 0 | DELETED | 20 | 30 | 40 | EMPTY |
此時有效元素數量由 降為 ,但搜尋剩餘元素的探查次數為:
- 搜尋 : 次
- 搜尋 :,共 次
- 搜尋 : 次
- 搜尋 : 次
平均搜尋次數變成:
也就是:
原因有兩層:
-
tombstone 仍會被搜尋穿越
DELETED雖然不再存放有效元素,卻不能作為搜尋終止條件。因此有效元素數量下降,探查路徑長度不一定縮短。 -
平均值取決於剩餘哪些元素
被刪除的 原本只需探查 格,刪除後這個較短的搜尋成本從平均值中消失;剩餘元素仍位於 cluster 尾端,平均值便會上升。
若將刪除後的資料重新雜湊,只有 時可排列成:
第 2 題30 分
【此題30分;每小題15分】
給定陣列A,容量為n,裡頭有n個正整數。我們打算用 insertion sort 對陣列A排序;並且我們要求排序的結果是陣列裡的元素「由小到大」排列。
(a) 假設陣列A是「k-亂序 (k-disordered)」,亦即每個元素距離其排序後的最終位置不超過k
個索引值,其中k為常數。請問在這種情況下,insertion sort的執行時間T(n)為何?用big-O
的方式表示。
(b) 考慮另一種情況:假設n為3的倍數,並且在陣列A裡頭,元素數值前三分
之一大的元素全部落在A[0]至A[(n/3)-1]裡頭。請問在這種情況下,insertion sort 的執行時
間T(n)為何?用big-O的方式表示。
註1:此題必須寫出推論過程;直接寫答案,此題0分。註2:用O(f(n))表示執行時間時,
f(n) 必須同時兼具 simplest 與 tightest 的型式。Tightest 的型式是指:若T(n)為O(f(n)),那
麼T(n) 就不能寫成O(g(n)),其中lim→∞ f(n)/g(n)=0。
登入後即可作答並保存紀錄。
核心觀念
Insertion sort 由左至右處理陣列。第 次插入時,已排序的前綴中,所有大於目前元素的值都必須向右移動一格。
令 表示陣列中的 inversion 數量:
Insertion sort 的執行時間與 inversion 數量直接相關:
其中 來自逐一掃描陣列, 來自元素的移動與比較。
(a) -亂序陣列
令元素原本位於索引 ,排序後位於索引 。由 -亂序定義:
考慮一組 inversion ,其中 且 。排序後, 必須位於 的右側,因此:
又因為每個元素最多偏離最終位置 :
因此:
整理得:
這表示 inversion 只能發生在相距 的元素之間。對每個元素而言,至多與 個附近元素形成 inversion,所以:
因此:
題目已明確指出 為常數,因此 也是常數:
此外,即使陣列原本已排序,Insertion sort 仍須逐一掃描 個元素,因此:
所以實際上:
(b) 前三分之一大的元素全部位於前一個三分之一
令:
第 3 題15 分
【此題15分】
給定陣列A = {3, 2, 1, 6, 5, 7, 9, 11, 14, 18},請問執行函式
build_max_heap(A)之後,陣列A的內容為何?註:給定陣列A,build_max_heap 函式的
功能是將陣列A調整成 max-heap。此題必須有推導過程;直接寫答案,此題0分。
登入後即可作答並保存紀錄。
核心觀念
本題考查:
-
Max-Heap 定義:對每一個節點,其鍵值皆大於或等於子節點,即
-
陣列表示完全二元樹:採用 1-based index 時,節點 的子節點為:
-
Bottom-Up Build-Max-Heap:葉節點本身已是合法 heap,因此從最後一個非葉節點開始,向前執行
max_heapify。
\left\lfloor \frac{n}{2} \right\rfloor
=\left\lfloor \frac{10}{2} \right\rfloor=5$$
所以處理順序為:
max_heapify 每次都將目前節點與較大的子節點交換,直到符合 max-heap 性質。
解題方法與推導
原始陣列採 1-based index 表示:
第 1 步:處理節點
節點 ,其左子節點為 。
因為 ,交換:
第 2 步:處理節點
節點 ,子節點為:
較大的子節點為 ,交換 與 :
第 3 步:處理節點
節點 ,子節點為:
較大的子節點為 ,交換:
第 4 題15 分
【此題15分】
一個graph是 simple graph,表示在該graph裡頭,任二點之間最多只有一條
edge 相連。小明學完資料結構課程之後,想到使用 divide-and-conquer 策略在 simple weighted
connected graph G上面尋找 minimum cost spanning tree T的recursive方法,如下:令V和E
分別表示 G的 vertex set 和 edge set。集合的絕對值表示集合裡的元素數量。如果1≤||≤2,
那麼 T等於G;否則將V分成二個沒有交集的子集合 Vi和2,並使得||和|V|最多相差1。
令 E₁ = {(u,v) ∈ E | u, v ∈ V₁} 且 E₂ = {(u,v) ∈ E | u,v∈V₂}。假設 E1和E2裡的minimum cost
spanning tree 分別為 T₁和 T2。令 E₃ = {(u,v) ∈ E | u∈V₁ 且 v∈V₂};令(α, β)表示 E3 裡頭
weight 最小的邊。那麼G裡頭的 minimum cost spanning tree T為TUTU(α, β)。請問:小明
這個尋找 minimum cost spanning tree T的 recursive 方法是否正確?如果你認為小明的方法正
確,寫「正確」即可,不必解釋理由;如果你認為小明的方法錯誤,請舉出反例,解說小明
的方法為何有錯。如果你認為小明的方法有錯,但舉不出反例,此題只給3分。
登入後即可作答並保存紀錄。
小明的遞迴演算法 錯誤。
反例
設 為 4 個頂點的簡單連通加權圖,分成兩個子集合
- 只在 內有邊 ,權重 。
- 只在 內有邊 ,權重 。
- 所有跨集合的邊都有權重 ,即
依照小明的方法
- 為 的 MST,只有邊 ,成本 。
- 為 的 MST,只有邊 ,成本 。
第 5 題10 分
【此題10分】
假設有一棵binary search tree,裡頭每個node代表一筆資料的key值,且key
值皆為介於100~1000之間的正整數。假設我們想在這個 binary search tree 裡頭尋找 key 值
為350的資料,那麼下列檢查次序,哪些是不可能發生的?找出答案,並解釋理由。
(A) 137→250→430→380→324→365→350
(B) 820→125→765→269→542→311→350
(C) 127→633→278→423→251→365→350
(D) 935→198→430→248→521→264→350
登入後即可作答並保存紀錄。
判斷原則
搜尋 時,每一步比較後的走向必須符合 BST 規則:
- 若目標 目前節點,下一個節點必須 較小(左子樹)
- 若目標 目前節點,下一個節點必須 較大(右子樹)
且在同一條路徑上,從上層節點往下的值範圍隨走向持續縮小。
檢查各選項
| 選項 | 比較與走向 | 是否符合範圍 |
|---|---|---|
| (A) 137→250→430→380→324→365→350 | 右、右、左、左、右、左 | 全部符合 |