110 身心障礙特考三等 資訊處理 資料結構 考古題詳解
第 一 題
在大數據分析的應用中,許多資料集是以稀疏矩陣(Sparse matrix)的方式呈現,例如客戶的購物行為等。這些資料集共同的特性是資料維度大,但其中的資料量相對稀少。若直接以傳統陣列結構來儲存資料,將會造成大量的空間浪費。請以 C 語言完成下列問題要求:
(一) 設計一有效的二維稀疏矩陣資料結構,避免儲存不存在(或其值為 )的資料,有效利用空間。( 分)
(二) 使用所設計的資料結構,完成矩陣的轉置(Transpose)運算函式。( 分)
(三) 使用所設計的資料結構,完成維度分別為 的 矩陣與 的 矩陣之矩陣相乘(Multiply)運算函式。( 分)
登入後即可作答並保存紀錄。
核心觀念
稀疏矩陣的非零元素遠少於所有元素的總數。若矩陣大小為 、非零元素數為 ,一般二維陣列需儲存 個值;稀疏表示法只記錄非零元素及其座標,空間需求可降為 。
以下採用三元組表示法:每個非零元素記錄列索引、行索引和值。索引採 C 語言常見的 0 起算方式。矩陣相乘則以列鏈結串列儲存各列的非零元素,方便依列走訪及累加乘積。
解題方法
(一)稀疏矩陣資料結構
三元組中的 row、col 與題目慣用的「列、行」方向容易混淆,因此程式碼以 row 表示矩陣的列索引、col 表示行索引。
typedef struct {
int row; // 列索引,0 起算
int col; // 行索引,0 起算
double value; // 非零值
} Term;
typedef struct {
int rows; // 矩陣列數
int cols; // 矩陣行數
int terms; // 非零元素數
Term *data; // 長度為 terms 的三元組陣列
} SparseMatrix;
data[k] 儲存一個非零元素及其座標。矩陣中值為 的元素不建立三元組,因此不占用儲存空間。三元組可依 (row, col) 排序;以下轉置程式會按列、行順序輸出結果。
(二)矩陣轉置
轉置會交換每個非零元素的列與行索引,並交換矩陣的列數與行數:
以下採簡單的逐欄掃描:依原矩陣的欄索引 c 由小到大掃描全部三元組。每次找到該欄的元素,就交換其索引後寫入結果。這樣輸出的三元組會依新矩陣的列、行順序排列,時間複雜度為 。
#include <stdlib.h>
int transpose(const SparseMatrix *src, SparseMatrix *dst)
{
dst->rows = src->cols;
dst->cols = src->rows;
dst->terms = src->terms;
dst->data = NULL;
if (src->terms == 0)
return 1;
dst->data = malloc((size_t)src->terms * sizeof(Term));
if (dst->data == NULL)
return 0;
int k = 0;
for (int c = 0; c < src->cols; ++c) {
for (int i = 0; i < src->terms; ++i) {
if (src->data[i].col == c) {
dst->data[k].row = src->data[i].col;
dst->data[k].col = src->data[i].row;
dst->data[k].value = src->data[i].value;
++k;
}
}
}
return 1;
}
呼叫成功後,dst->data 由呼叫端負責釋放;來源與目的矩陣應使用不同的結構,避免覆寫來源資料。
(三)矩陣相乘
令 為 矩陣, 為 矩陣,則乘積 的大小為 ,元素定義為:
只有當 與 都是非零值時,才會對 累加乘積。以下將三元組依列分組成鏈結串列,讓程式依序取得 的第 列,以及 中列索引等於 的元素。
第 二 題
【題組共用題幹】
一有向圖形(directed graph)如下圖所示,圖中包含節點 、、、、及各邊之權重。
(一) 請以相鄰矩陣(adjacency matrix)表達有向圖形 。( 分)
(二) 設計一演算法找尋圖形中所有端點(node)對端點的最短路徑(all-pairs shortest path),並以有向圖形 的相鄰矩陣為例,說明所使用演算法的計算過程。( 分)
(三) 請說明在上述(二)中所使用演算法的時間複雜度(time complexity)為何?( 分)
登入後即可作答並保存紀錄。
核心觀念
本題考有向加權圖的相鄰矩陣,以及 Floyd–Warshall 全點對最短路徑演算法。相鄰矩陣的列代表出發點、欄代表到達點;若有邊,填入該邊權重,若無邊則填入 ,對角線填 。
解題方法
依圖中箭頭方向讀取邊,矩陣列、欄順序均採 。例如, 權重為 ,所以第 列、第 欄填 ;反向的 權重為 ,因此第 列、第 欄填 。
(一)相鄰矩陣
此矩陣是加權有向圖的相鄰矩陣; 表示從節點 到節點 的直接邊權重。
(二)Floyd–Warshall 演算法
依序把 當作中繼點。令 表示只允許前 個節點作為中繼點時,從 到 的最短距離,更新公式為:
每次更新都比較「目前距離」與「經過新中繼點的距離」,取較小值。計算結果如下,矩陣列、欄順序皆為 。
初始矩陣 :
以 為中繼點後, 更新為 , 更新為 ; 更新為 , 更新為 :
第 三 題
對資料庫系統的檔案儲存結構而言,必須能夠隨著檔案資料的增多,動態新增儲存區塊(block)。例如:B-tree 樹狀檔案資料結構,即可隨著資料量變大而增加葉節點區塊(leaf node block),或增加樹的高度來因應。
下列為 (5-way)B-tree 的現況,目前已存有 筆資料:
根節點包含:、
其子節點依序包含:
- 、、
- 、、、
- 、、、
(一) 請問具有 層以上、 結構的 B-tree 至少可以存放多少筆資料?( 分)
(二) 請畫出完成運算 與 後的 B-tree 結構。( 分)
(三) 完成上述(二)之後,接續畫出先後完成運算 與 的 B-tree 結構。( 分)
登入後即可作答並保存紀錄。
核心觀念
表示每個節點最多有 個子節點、最多存放 個鍵值。非根節點至少有 個子節點,因此至少有 個鍵值;根節點至少有 個鍵值。節點鍵值超過上限時,將中間鍵值提升至父節點,並把節點分成左右兩個節點;若父節點也溢位,分裂會向上傳遞。
(一) 層以上的 B-tree 最少資料筆數
要讓樹具有至少 層,採用每層節點數及鍵值數皆為最少的結構:
- 根節點有 個鍵值,並至少有 個子節點。
- 根的下一層有 個節點;之後每個非根內部節點至少有 個子節點。
- 每個非根節點至少有 個鍵值。
因此,第 層(根為第 層,)最少有 個節點,各有 個鍵值。總筆數為
所以,具有 層以上的 -way B-tree 最少可存放
(二)依序執行 與
初始根節點為 ,三個子節點依序為 、、。
插入 後,第一個葉節點成為 ,未超過每個節點最多 個鍵值的限制。
第 四 題
霍夫曼碼(Huffman code)是具有最佳編碼的資料壓縮方法之一。今有下列訊息欲以霍夫曼碼編碼傳遞,以節省訊息量:
“PAPAYA_AND_BANANA_ARE_YUMMY”
其中空格「_」亦需計算在訊息量內。
(一) 請以該訊息詳述構建霍夫曼碼演算法的過程與結果。( 分)
(二) 依步驟說明所使用演算法的時間複雜度(time complexity)。( 分)
登入後即可作答並保存紀錄。
核心觀念
霍夫曼碼(Huffman code)是一種最佳前綴碼:任何一個字元的編碼都不是另一個字元編碼的前綴,因此解碼時不需要分隔符號。
建構時反覆選取目前頻率最低的兩個節點,合併成一個頻率為兩者總和的父節點,直到只剩一個根節點。由根走到葉節點的路徑形成該字元的碼字;每次向左記為 ,向右記為 。低頻字元通常位於較深處,高頻字元則通常位於較淺處,以降低加權碼長。
解題方法
先計算訊息中每個字元的出現次數。訊息共有 個字元,包含 4 個底線:
| 字元 | 頻率 |
|---|---|
| A | 8 |
| _ | 4 |
| N | 3 |
| Y | 3 |
| M | 2 |
| P | 2 |
| B | 1 |
| D | 1 |
| E | 1 |
| R | 1 |
| U | 1 |
頻率總和為 。為使合併過程與碼字明確,以下遇到同頻節點時,以字元名稱及子樹內字元名稱的字典序決定先後;每次合併中,頻率較小者置左,並以左枝 、右枝 記碼。霍夫曼碼遇到同頻節點時可以有不同的合併順序,因此碼字不唯一,但都能達到最佳加權碼長。
建構霍夫曼樹
依序合併兩個最低頻率的節點:
| 步驟 | 合併節點 | 新節點頻率 |
|---|---|---|
| 1 | B(1) 與 D(1) | 2 |
| 2 | E(1) 與 R(1) | 2 |
| 3 | U(1) 與 BD(2) | 3 |
| 4 | ER(2) 與 M(2) | 4 |
| 5 | P(2) 與 N(3) | 5 |
| 6 | Y(3) 與 UBD(3) | 6 |
| 7 | _(4) 與 ERM(4) | 8 |
| 8 | PN(5) 與 YUBD(6) | 11 |
| 9 | _(ERM)(8) 與 A(8) | 16 |
| 10 | 11 與 16 | 27 |
最後只剩頻率 的根節點,建樹完成。沿樹由根至葉記錄 、,得到一組霍夫曼碼:
| 字元 | 頻率 | 霍夫曼碼 |
|---|---|---|
| A | 8 | 11 |
| _ | 4 | 100 |
| N | 3 | 001 |
| Y | 3 | 10 |
| M | 2 | 1011 |
| P | 2 | 000 |
| B | 1 | 1110 |
| D | 1 | 1111 |
| E | 1 | 10100 |
| R | 1 | 10101 |
| U | 1 | 110 |