112 年 國立臺北大學資訊工程研究所《資料結構與演算法》

📄 試題原卷 免費註冊後即可對照原始考卷 PDF免費註冊

第 1 題15 分

Run the Breadth-First Search (BFS) algorithm to generate a BFS searching tree which has the node s as its root. Run the algorithm step by step.

🖼️【此處有附圖,請對照原卷】
(圖片包含一個無向圖,節點有 a, b, c, d, e, s。邊有 (a,s), (b,s), (c,s), (c,b), (d,s), (d,e))

🖼️ 本題含圖表,以下為原卷對應頁面:
原卷第 1 頁

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

BFS(Breadth-First Search,廣度優先搜尋)使用佇列(Queue),從根節點 ss 開始,依照「距離起點由近到遠」的順序拜訪節點。

BFS 的規則如下:

  1. 將起點 ss 標記為已拜訪並放入佇列。
  2. 反覆取出佇列前端節點。
  3. 依序檢查其鄰接節點;尚未拜訪者標記為已拜訪、設定其父節點,並加入佇列。
  4. 每個節點第一次被發現時,便加入 BFS 樹,其父子邊即為樹邊。

題目圖形為無向圖,邊集合為

(a,s),(b,s),(c,s),(c,b),(d,s),(d,e).(a,s),(b,s),(c,s),(c,b),(d,s),(d,e).

因此各節點的鄰接關係為:

  • ss:a,b,c,da,b,c,d
  • aa:ss
  • bb:s,cs,c
  • cc:s,bs,b
  • dd:s,es,e
  • ee:dd

以下依題目列出的鄰接順序處理。

解題方法:逐步執行 BFS

初始狀態:

  • 已拜訪集合:{s}\{s\}
  • 佇列:[s][s]
  • BFS 樹:根節點為 ss
步驟取出節點新發現節點佇列狀態新增樹邊
1ssa,b,c,da,b,c,d[a,b,c,d][a,b,c,d](s,a),(s,b),(s,c),(s,d)(s,a),(s,b),(s,c),(s,d)
2aa無[b,c,d][b,c,d]無
3bb無;cc 已發現[c,d][c,d]無
4cc無;bb 已發現[d][d]無
5ddee[e][e](d,e)(d,e)
6ee無;dd 已發現[][]無

其中:

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 2 題10 分

Run the merge sort on the following array: (5,1,8,3,6,4,7,2) step by step.
🖼️【此處有附圖,請對照原卷】
(圖片包含一個無向圖,節點有 a, b, c, d, e, s。邊有 (a,s), (b,s), (c,s), (c,b), (d,s), (d,e))

🖼️ 本題含圖表,以下為原卷對應頁面:
原卷第 1 頁

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

Merge Sort(合併排序)採用「分割與征服」策略:

  1. 將陣列遞迴分割成單一元素。
  2. 將相鄰且已排序的子陣列兩兩合併。
  3. 合併時依序比較兩邊最前面的元素,較小者先放入結果。

時間複雜度為 O(nlog⁡n)O(n\log n),額外空間複雜度為 O(n)O(n)。

題目文字要求排序陣列 (5,1,8,3,6,4,7,2)(5,1,8,3,6,4,7,2);附圖內容為無向圖,與本題 Merge Sort 無關,因此排序過程依題目文字中的陣列作答。

解題方法:分割階段

原始陣列:

(5,1,8,3,6,4,7,2)(5,1,8,3,6,4,7,2)

第一次分割:

(5,1,8,3)(6,4,7,2)(5,1,8,3)\quad (6,4,7,2)

第二次分割:

(5,1)(8,3)(6,4)(7,2)(5,1)\quad (8,3)\quad (6,4)\quad (7,2)

分割至單一元素:

(5) (1) (8) (3) (6) (4) (7) (2)(5)\ (1)\ (8)\ (3)\ (6)\ (4)\ (7)\ (2)

解題方法:合併階段

先合併相鄰的單一元素:

(5)+(1)→(1,5)(5)+(1)\rightarrow(1,5) (8)+(3)→(3,8)(8)+(3)\rightarrow(3,8) (6)+(4)→(4,6)(6)+(4)\rightarrow(4,6) (7)+(2)→(2,7)(7)+(2)\rightarrow(2,7)

此時陣列分成四個已排序子陣列:

(1,5)(3,8)(4,6)(2,7)(1,5)\quad(3,8)\quad(4,6)\quad(2,7)

接著合併兩兩子陣列:

合併 (1,5)(1,5) 與 (3,8)(3,8):

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 3 題10 分

Give an asymptotic upper bound for the function T(n) where T(n) satisfies the recurrent equation T(n)=3T(n/4])+n2T(n)=3T(n/4]) + n^2 for integer n>2n>2 and T(2)T(2) is a constant.
🖼️【此處有附圖,請對照原卷】
(圖片包含一個無向圖,節點有 a, b, c, d, e, s。邊有 (a,s), (b,s), (c,s), (c,b), (d,s), (d,e))

🖼️ 本題含圖表,以下為原卷對應頁面:
原卷第 1 頁

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考遞迴式的漸進複雜度,可使用 Master Theorem:

T(n)=aT(nb)+f(n)T(n)=aT\left(\frac{n}{b}\right)+f(n)

其中:

  • a=3a=3
  • b=4b=4
  • f(n)=n2f(n)=n^2

先計算:

nlog⁡ba=nlog⁡43n^{\log_b a}=n^{\log_4 3}

因為 log⁡43<1\log_4 3<1,所以:

nlog⁡43=O(n0.793)n^{\log_4 3}=O(n^{0.793})

而 f(n)=n2f(n)=n^2 的成長速度明顯較快。

解題方法

比較 f(n)f(n) 與 nlog⁡43n^{\log_4 3}:

n2=Ω(nlog⁡43+ε)n^2=\Omega\left(n^{\log_4 3+\varepsilon}\right)

取適當的 ε>0\varepsilon>0 即可成立,因此符合 Master Theorem 的第三種情況。若正規性條件成立:

af(nb)=3(n4)2=316n2≤cn2a f\left(\frac{n}{b}\right) =3\left(\frac{n}{4}\right)^2 =\frac{3}{16}n^2 \leq cn^2

其中 c=316<1c=\frac{3}{16}<1,故:

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 4 題15 分

We have a set of n open intervals S={(aᵢ,bᵢ): i=1,..,n}. We want to choose a largest subset S' ⊆ S such that the selected intervals in S' are mutually disjoint. Please give an O(nlog n)-time algorithm to solve this problem.
🖼️【此處有附圖,請對照原卷】
(圖片包含一個無向圖,節點有 a, b, c, d, e, s。邊有 (a,s), (b,s), (c,s), (c,b), (d,s), (d,e))

🖼️ 本題含圖表,以下為原卷對應頁面:
原卷第 1 頁

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題考的是 區間排程(Interval Scheduling) 與 貪心演算法(Greedy Algorithm)。

對兩個開區間 (ai,bi)(a_i,b_i) 與 (aj,bj)(a_j,b_j),若要互不相交,排序後可檢查:

aj≥bia_j \ge b_i

由於題目使用的是「開區間」,當 aj=bia_j=b_i 時,兩區間不包含端點,仍然互不相交。


解題方法

採用「每次選擇結束時間最早的區間」:

  1. 將所有區間依右端點 bib_i 遞增排序。

  2. 依序掃描排序後的區間。

  3. 若目前區間的左端點滿足

    ai≥lastEnda_i \ge \text{lastEnd}

    就選取該區間,並令

    lastEnd=bi\text{lastEnd}=b_i

  4. 掃描結束後,所選區間即為最大互不相交子集合。

初始時令 lastEnd=−∞\text{lastEnd}=-\infty。

偽程式碼:

GreedyIntervalSchedule(S):
    將 S 依 b_i 遞增排序
    selected = []
    lastEnd = -∞

    for each interval (a_i, b_i) in S:
        if a_i >= lastEnd:
            將 (a_i, b_i) 加入 selected
            lastEnd = b_i

    return selected

正確性說明

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 5 題5 分

(A) 在 C 語言中, int list[5] 和 int *plist[5] 有何不同, 要如何將 int *plist[5] 實作
為 2 維陣列?

(B) 將此 inorder statement : A∗B+C∗(D−E)/(F+H)A*B+C*(D-E)/(F+H) 轉為 postorder, 並畫出它的二元樹。
須按照以左到右讀取順序來做, 以達到單一解答。同時, 設計一個算法使用 stack 來實現上述
inorder 轉 postorder, 並且以上述 statement 說明如何使用 stack 來做轉換。
🖼️【此處有附圖,請對照原卷】
(圖片包含一個無向圖,節點有 a, b, c, d, e, s。邊有 (a,s), (b,s), (c,s), (c,b), (d,s), (d,e))

🖼️ 本題含圖表,以下為原卷對應頁面:
原卷第 1 頁

登入後即可作答並保存紀錄。

這一題的完整詳解

(A)int list[5] 與 int *plist[5] 的差異

核心觀念

  • int list[5]:宣告一個含有 5 個 int 的陣列。
  • int *plist[5]:宣告一個含有 5 個「指向 int 的指標」之陣列。

兩者的記憶體配置不同:

int list[5];

可視為:

list[0], list[1], list[2], list[3], list[4]

每個元素直接儲存一個整數。

int *plist[5];

則是:

plist[0], plist[1], ..., plist[4]

每個元素儲存一個位址,因此每一列可以指向不同長度的整數陣列,形成不規則的二維陣列。

解題方法:逐列配置二維陣列

假設要建立 5×n5 \times n 的二維陣列:

#include <stdlib.h>

int rows = 5;
int cols = n;

int *plist[5];

for (int i = 0; i < rows; i++) {
    plist[i] = malloc(cols * sizeof(int));
}

之後即可使用二維陣列的方式存取:

plist[i][j] = 10;
printf("%d", plist[i][j]);

使用完畢後必須逐列釋放:

for (int i = 0; i < rows; i++) {
    free(plist[i]);
}

若希望使用一整塊連續記憶體,也可以寫成:

int *data = malloc(rows * cols * sizeof(int));
int *plist[5];

for (int i = 0; i < rows; i++) {
    plist[i] = data + i * cols;
}

此時 plist[i][j] 等價於:

data[i * cols + j]

複雜度與技巧

  • 配置時間:O(rows)O(rows);若包含初始化全部元素,則為 O(rows×cols)O(rows \times cols)。
  • 額外指標空間:O(rows)O(rows)。
  • int *plist[5] 的每一列可獨立配置,因此適合建立不規則二維陣列。
  • 常見錯誤是把 int *plist[5] 誤認為真正連續的二維陣列;它本質上是「指標陣列」。

(B)Inorder 轉 Postorder 與二元樹

核心觀念

原式為:

A∗B+C∗(D−E)/(F+H)A*B+C*(D-E)/(F+H)

運算優先順序為:

括號>∗、/>+、−括號 > *、/ > +、-

同一層級的 *、/、+、- 皆採由左至右結合,因此原式可分組為:

(A∗B)+C∗(D−E)F+H(A*B)+\frac{C*(D-E)}{F+H}

二元樹

          +
        /   \
       *     /
      / \   / \
     A   B *   +
          / \ / \
         C  - F  H
            / \
           D   E

Postorder 結果

Postorder 的走訪順序為:

左子樹→右子樹→根節點左子樹 \rightarrow 右子樹 \rightarrow 根節點

因此:

🔒

後續完整解題步驟與【答案】

免費註冊,享三天全站完整詳解閱覽。

免費註冊

第 6 題10 分

使用 linked list 實作 stack,運用以下 C 語言程式:

typedef struct node { int value; node *next; }

void push(node **top, int new_value) { // assume top is not null
node *new_node = (node *) malloc (sizeof(node));

// 實作以下敘述
// add new_node to stack by top

}

int pop(node **top) { // assume top is not null
int value;
node *deleting_node = *top;

// 實作以下敘述
// remove the deleting node from stack, get the value of deleting node

free(deleting_node);
return value;

}

登入後即可作答並保存紀錄。

這一題的完整詳解
載入中…

第 7 題15 分

使用 stack 解決老鼠走迷宮問題(Maze path search),設計並描述如何實作,包含:

(A) 如何搜尋四個方向來移動
(B) 如何找到合法移動和出口
(C) 解決死路問題

登入後即可作答並保存紀錄。

這一題的完整詳解
載入中…

其他考古題