109 年 國立成功大學資訊管理研究所乙組《資料結構》

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

第 1 題

In each of the following question, please specify if the statement is true or false.
a. [2%] n1.5=O(nlog⁡n)n^{1.5} = O(n \log n)
b. [2%] A complete binary tree with a height of hh can have more nodes than a full binary tree with a height of hh.
c. [2%] When we use a max heap to implement a priority queue, the time complexity of both the add and delete operations are O(n)O(n).
d. [4%] T(n)=T(n−1)+nT(n) = T(n − 1) + n, T(1)=1T(1) = 1. Then T(n)=O(n3)T(n) = O(n^3)

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

這一題的完整詳解

a. n1.5=n3/2n^{1.5}=n^{3/2} 的增長速率比 nlog⁡nn\log n 快,因為 lim⁡n→∞n3/2nlog⁡n=lim⁡n→∞nlog⁡n=∞\displaystyle\lim_{n\to\infty}\frac{n^{3/2}}{n\log n}= \lim_{n\to\infty}\frac{\sqrt n}{\log n}= \infty。故 n1.5≠O(nlog⁡n)n^{1.5}\neq O(n\log n)。
答案:False

b. 完全二元樹(complete binary tree)在每層除了最底層外皆滿,且最底層的節點盡可能靠左;滿二元樹(full binary tree)要求每個節點要么是葉子要么有兩個子節點。給定相同高度 hh,滿二元樹的節點數恰好是 2h+1−12^{h+1}-1,而完全二元樹的節點數上限同樣是 2h+1−12^{h+1}-1,下限則為 2h2^{h}。

🔒

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

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

免費註冊

第 2 題

In computer science, a priority queue is an abstract data type which is like a regular queue, but each element has a "priority" associated with it. Elements with higher priorities are served before elements with lower priorities.
a. [5%] Design a data structure in C++ or Java to represent priority queues where both the data and the priority are integers. Note: 1. Only the class definition is required; 2. The size of the queue should only be constrained by the memory space; 3. Your design should allow efficient enqueue and dequeue operations; 4. The use of STL classes is prohibited.
b. [10%] Implement the enqueue and dequeue operations/methods.

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

這一題的完整詳解

核心觀念

Priority queue(優先佇列)與一般 queue 的差異在於:

  • 一般 queue 依照先進先出(FIFO)。
  • Priority queue 依照 priority 決定服務順序,priority 較高者優先 dequeue。
  • 本題要求 enqueue 與 dequeue 都有效率,且不能使用 STL,因此適合使用二元最大堆積(max heap)。

以最大堆積儲存資料時,必須滿足:

parent.priority≥child.priority\text{parent.priority} \geq \text{child.priority}

因此根節點永遠是最高優先權元素,可在 O(1)O(1) 時間找到;enqueue 與 dequeue 透過調整堆積維持結構,時間複雜度皆為 O(log⁡n)O(\log n)。


解題方法

每個元素包含兩個整數:

data      // 資料
priority  // 優先權

採用陣列儲存二元最大堆積。若節點位於索引 ii:

parent(i)=⌊i−12⌋\text{parent}(i)=\left\lfloor\frac{i-1}{2}\right\rfloor left(i)=2i+1,right(i)=2i+2\text{left}(i)=2i+1,\qquad \text{right}(i)=2i+2

陣列容量不足時,配置一個容量加倍的新陣列,將原資料複製過去,因此佇列大小只受可用記憶體限制。


a. 資料結構設計

class PriorityQueue {
private:
    struct Node {
        int data;
        int priority;
    };

    Node* heap;
    int size;
    int capacity;

    void resize();
    void swap(Node& a, Node& b);

public:
    PriorityQueue();
    ~PriorityQueue();

    void enqueue(int data, int priority);
    bool dequeue(int& data, int& priority);

    bool empty() const;
};

其中:

  • heap:存放最大堆積的陣列。
  • size:目前元素數量。
  • capacity:目前陣列容量。
  • 根節點 heap[0] 的 priority 最大。
  • dequeue 回傳 false 表示佇列為空。

b. enqueue 與 dequeue 實作

enqueue

新元素先放在陣列最後,接著向上調整:

  1. 將新元素放到索引 size。
  2. 與父節點比較 priority。
  3. 若新元素 priority 較高,便與父節點交換。
  4. 持續向上直到符合最大堆積性質。

dequeue

刪除根節點:

  1. 取出根節點作為 dequeue 結果。
  2. 將最後一個元素移到根節點。
  3. 將此元素向下調整:
    • 找出左右子節點中 priority 較高者。
    • 若子節點 priority 高於目前節點,便交換。
    • 持續向下直到符合最大堆積性質。
🔒

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

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

免費註冊

第 3 題

Answer the following question regarding Red-Black tree
a. [2%] Define red-black tree
b. [8%] What is the big O performance (in terms of the number of nodes in the tree) for the operations find, insert, and remove for a red-black tree in the best and worst cases?
c. [10%] Show the tree that results from inserting the values 2, 1, 4, 5, 9, 3, 6, 7 into an initial empty red-black tree. Show the tree after each insertion.

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

這一題的完整詳解

a. 定義
紅黑樹(Red‑Black Tree)是一種滿足以下五條性質的二元搜尋樹:

  1. 每個節點皆為紅色 (R) 或黑色 (B)。
  2. 根節點為黑色。
  3. 所有葉子 NIL(外部空節點)皆為黑色。
  4. 若一個節點為紅色,則其兩個子節點皆為黑色(紅色節點不可相鄰)。
  5. 任一節點到其各子孫葉子 NIL 的所有簡單路徑上,黑色節點數目相同(稱為 黑高)。

b. 時間複雜度(以節點數 nn 計)

操作最佳情況最差情況
FindO(log⁡n)O(\log n)(樹高受限於 2log⁡2(n+1)2\log_2(n+1))O(log⁡n)O(\log n)
InsertO(log⁡n)O(\log n)(搜尋 + 最多 22 次旋轉 + 重新著色)O(log⁡n)O(\log n)
RemoveO(log⁡n)O(\log n)(搜尋 + 最多 33 次旋轉 + 重新著色)O(log⁡n)O(\log n)

c. 插入序列 2,1,4,5,9,3,6,72,1,4,5,9,3,6,7 的逐步結果
節點顯示格式:value(color);黑色 B、紅色 R。

  1. 插入 2 → 只剩根節點,重新著色為黑色。

    2B
    
  2. 插入 1 → 1 為左子,顏色 R;根 2 仍 B。

      2B
     /
    1R
    
  3. 插入 4 → 4 為右子,顏色 R。

      2B
     / \
    1R 4R
    
  4. 插入 5 → 插入為 4 的右子 (5R),違反連續紅色 (4R‑5R)。
    重新著色:4 變 B,5 變 R,根 2 仍 B。

🔒

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

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

免費註冊

第 4 題

[5%] Given an expression, such as "{[2 × (a + b)] - c} × 3(d + e)", implement a function in C++ or Java that checks the proper opening and closing of parenthesis.

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

這一題的完整詳解

核心觀念

本題考查「堆疊(Stack)」在括號配對與巢狀結構檢查上的應用。

括號必須同時滿足兩項條件:

  1. 每個右括號都要有對應的左括號。
  2. 括號的配對順序必須正確,先開啟的括號要最後關閉。

例如:

  • {[2 × (a + b)] - c}:正確
  • ([ ]):正確
  • ([)]:錯誤,( 尚未關閉就遇到 ]
  • ((a+b):錯誤,最後仍有左括號未配對
  • (a+b)):錯誤,多出一個右括號

這種「後開先關」的特性正好符合堆疊的後進先出(Last In, First Out, LIFO)原則。


解題方法

由左至右掃描整個運算式:

  1. 遇到左括號 (、[、{:推入堆疊。
  2. 遇到右括號 )、]、}:
    • 若堆疊為空,表示沒有可配對的左括號,直接判定錯誤。
    • 取出堆疊頂端的左括號。
    • 檢查兩者是否為同一種類型;不相符則判定錯誤。
  3. 掃描結束後:
    • 堆疊為空,表示所有括號均已配對,運算式正確。
    • 堆疊不為空,表示仍有左括號未關閉,運算式錯誤。

以題目中的片段為例:

{ [ 2 × ( a + b ) ] - c }

括號處理順序如下:

掃描到的符號堆疊內容動作
{{推入
[{ [推入
({ [ (推入
){ [與 ( 配對並移除
]{與 [ 配對並移除
}空與 { 配對並移除

掃描結束時堆疊為空,因此括號排列正確。


C++ 參考實作

🔒

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

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

免費註冊

第 5 題

True or False, and EXPLAIN
Choose T(true) or F(false). If the statement is correct, briefly state why. If the statement is wrong, explain why or give a counterexample. Answers WITHOUT reasons will get at most 1 point.
a. [4%] (T, F) If we want to randomize the ordering of n integers A[1],...,A[n], we can generate another n random numbers B[1],...,B[n] with values in [−n3,n3][-n^3, n^3], and then sort B[•] in ascending order. We can then use this ordering to reorder A[1],...,A[n]. Therefore, to randomize n integers takes O(nlog⁡n)O(n \log n) time.
b. [4%] (T, F) Let f(x)=∑i=0mAixif(x) = \sum_{i=0}^{m} A_i x^i, g(x)=∑j=0nBjxjg(x) = \sum_{j=0}^{n} B_j x^j, f(x)+g(x)=∑k=0max⁡(m,n)Ckxkf(x)+g(x) = \sum_{k=0}^{\max(m,n)} C_k x^k, and f(x)⋅g(x)=∑l=0m+nDlxlf(x) \cdot g(x) = \sum_{l=0}^{m+n} D_l x^l. Calculating CkC_k and DlD_l takes O(max⁡{m,n})O(\max\{m,n\}) and O(mn)O(mn) time, respectively.
c. [4%] (T, F) Based on (b), if A[] and B[] store their p and q non-zeros in two ordered doubly linked lists in ascending order. Then, to calculate CkC_k and DlD_l takes O(p+q)O(p+q) and O(pq)O(pq) time, respectively.
d. [4%] (T, F) For a binary search tree of n integers, if we insert an integer of new value to the tree, and then delete that integer right away. It is possible the tree structure becomes different from its original form.
e. [4%] (T, F) Given a complete undirected graph KnK_n with n nodes, let cij>0c_{ij}>0 represent the length of any edge (i,j). We can use Dijkstra's algorithm to find a shortest simple path that has to pass all n nodes.
f. [4%] (T, F) Given an undirected graph G=(N,A)G=(N,A) of ∣N∣=n|N|=n nodes and ∣A∣=m|A|=m arcs, let cij≥0c_{ij} \ge 0 represent the length of (i,j)∈A(i, j) \in A. To detect whether there is a zero-length cycle passing node i takes O(m)O(m) time.
g. [4%] (T, F) Given a Taipei city street map composed by street segments with n nodes and m arcs, where an arc is a street segment with two adjacent nodes. The average degree for a node is Ω(n)\Omega(n).
h. [4%] (T, F) To build a min-heap of n values, it takes O(nlog⁡n)O(n \log n) time.

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

這一題的完整詳解

核心觀念

本題綜合考查:

  • 隨機排列與排序複雜度
  • 多項式加法、乘法與稀疏表示法
  • Binary Search Tree(BST)的插入與刪除
  • Dijkstra 最短路徑與 Hamiltonian path
  • 零權重 cycle 的判定
  • 圖的平均 degree
  • Min-heap 建構方法

a. 隨機排序整數

答案:F

產生 B[1],…,B[n]B[1],\ldots,B[n] 後依照 BB 的大小排序,再用此順序排列 AA,排序本身確實可在 O(nlog⁡n)O(n\log n) 時間完成;但這不代表一定能產生均勻的隨機排列。

原因是 B[i]B[i] 是整數,可能出現相同值。例如:

B[1]=B[2]B[1]=B[2]

此時兩個元素的先後順序必須依賴排序法的 tie-breaking 規則。若相同值時維持原順序,則部分排列的機率會不同,無法保證每個排列都等機率出現。

雖然取值範圍 [−n3,n3][-n^3,n^3] 很大,使碰撞機率很低,但碰撞機率仍不等於 00。因此這個方法不能嚴格保證隨機化排列。

此外,正確的 Fisher–Yates shuffle 可在 O(n)O(n) 時間完成,因此「隨機化需要 O(nlog⁡n)O(n\log n)」也不是最佳複雜度。


b. 稠密多項式的加法與乘法

答案:T

多項式加法為:

f(x)+g(x)=∑k=0max⁡(m,n)Ckxkf(x)+g(x)=\sum_{k=0}^{\max(m,n)}C_kx^k

其中

Ck=Ak+BkC_k=A_k+B_k

缺少的係數可視為 00。需要逐項處理至次數 max⁡(m,n)\max(m,n),所以時間複雜度為:

O(max⁡{m,n})O(\max\{m,n\})

多項式乘法中:

Dl=∑i+j=lAiBjD_l=\sum_{i+j=l}A_iB_j

每個 AiA_i 都必須與每個 BjB_j 相乘,共有:

(m+1)(n+1)=O(mn)(m+1)(n+1)=O(mn)

個乘積,因此直接計算的時間複雜度為:

O(mn)O(mn)

所以敘述正確。


c. 稀疏多項式的加法與乘法

答案:T

設第一個多項式有 pp 個非零項,第二個多項式有 qq 個非零項,且兩者都依指數遞增排列。

多項式加法

兩個有序 linked list 可以使用類似 merge 的方法:

  1. 比較目前兩個節點的指數。
  2. 指數較小者直接放入結果。
  3. 指數相同時,將兩個係數相加。
  4. 移動相應的指標。

每個節點最多被走訪一次,因此:

Taddition=O(p+q)T_{\text{addition}}=O(p+q)

多項式乘法

每個非零項都要與另一個多項式的每個非零項相乘:

p×qp\times q

個乘積。每個乘積會產生一項:

AiBjxi+jA_iB_jx^{i+j}

將指數相同的項合併後,總處理量仍受 pqpq 個非零項乘積所限制,因此:

Tmultiplication=O(pq)T_{\text{multiplication}}=O(pq)

稀疏表示的重點是複雜度依非零項數 p,qp,q 計算,而不是依最大次數 m,nm,n 計算。


d. BST 插入後立即刪除

答案:F

在 BST 中插入一個「新值」時,由於該值原本不存在,最後一定會被插入成葉節點。

例如原本有:

10/\515\begin{array}{c} 10\\ /\quad \backslash\\ 5\quad 15 \end{array}

插入新值 1212 後:

10/\515/\12\begin{array}{c} 10\\ /\quad \backslash\\ 5\quad 15\\ \quad /\quad \backslash\\ \quad 12 \end{array}

新節點 1212 沒有子樹,因此刪除它只需直接移除該葉節點,原本的樹形會完全恢復。

所以「插入新值後立即刪除,樹結構可能改變」是錯誤的。


e. 使用 Dijkstra 找出通過所有節點的最短路徑

答案:F

Dijkstra 演算法解決的是:

從單一起點到各節點的最短路徑問題。

🔒

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

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

免費註冊

第 6 題

Given a simple directed network G-(N,A) of n=|N| nodes Am arcs, let c ≥ 0, xij and Uij represent the length, flow, and capacity for (i, j) ∈ A. If n is even and U = max(i, j)∈ A {uij}, }, we want to send a flow of F units for n/2 pairs (or,dx)=(k,k+n/2), k=1,...,n/ 2. Answer the following questions:
a. [6%] Briefly explain how to determine whether F₁ can be successfully sent without violating the arc capacity from the origin node 1 to the destination node 1+n/2. What is the complexity of your method?
b. [6%] Briefly explain how to construct a sub-network G₁ = (N, A₁) which only contains required nodes and arcs on all possible shortest paths (i.e., the minimum number of arcs) connecting from an origin node or to a destination node d₁. What is the complexity of your method?
c. [6%] Suppose the complexity of your method in (a) is S(n,m,U) time. To send all the flows of Fe units for each k=1,..., n/2 at the same time, briefly explain how to determine whether this is possible or not (if we cannot send F units for some k). Is there a method that can do this in O(S(n,m,U)) time?

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

這一題的完整詳解

核心觀念

本題主要考查三個觀念:

  1. 單一來源—單一目的地的最大流(maximum flow)。
  2. 最短路徑網路(shortest-path subnetwork)的建構。
  3. 多商品流(multicommodity flow)與不同流量間的容量競爭。

對任一弧 (i,j)∈A(i,j)\in A,容量限制為

0≤xij≤uij.0\le x_{ij}\le u_{ij}.

若要從來源 oo 傳送 FF 單位流量至目的地 dd,只要最大流值滿足

maxflow⁡(o,d)≥F,\operatorname{maxflow}(o,d)\ge F,

即可判定能否成功傳送。


(a) 判定從節點 11 傳送至節點 1+n/21+n/2

解題方法

令

o1=1,d1=1+n2.o_1=1,\qquad d_1=1+\frac n2.

將原網路 G=(N,A)G=(N,A) 視為一個容量網路,對每條弧設定容量 uiju_{ij},接著執行最大流演算法,例如 Ford–Fulkerson 演算法:

  1. 初始流量設為 00。

  2. 在殘餘網路中尋找一條由 o1o_1 到 d1d_1 的增廣路徑。

  3. 沿增廣路徑增加可行流量:

    Δ=min⁡(i,j) 在增廣路徑上rij,\Delta=\min_{(i,j)\text{ 在增廣路徑上}} r_{ij},

    其中 rijr_{ij} 為弧 (i,j)(i,j) 的殘餘容量。

  4. 重複上述步驟,直到:

    • 最大流值達到 FF;或
    • 殘餘網路中不存在從 o1o_1 到 d1d_1 的路徑。

若最大流值至少為 FF,則可以成功傳送;否則無法成功傳送。

根據最大流最小割定理,也可以改以判斷是否存在一個 o1o_1–d1d_1 割,其容量小於 FF。若最小割容量小於 FF,必然無法傳送 FF 單位流量。

複雜度

若採用 Ford–Fulkerson,且容量為整數,每次增廣至少增加 11 單位流量,因此時間複雜度為

O(mFmax⁡),O(mF_{\max}),

其中 Fmax⁡F_{\max} 為最大流量。

因為每條弧容量至多為

U=max⁡(i,j)∈Auij,U=\max_{(i,j)\in A}u_{ij},

且網路中最多有 nn 個節點,所以可使用較寬鬆的上界

Fmax⁡≤nU.F_{\max}\le nU.

因此複雜度可寫為

O(nmU).O(nmU).

若使用 Edmonds–Karp 等較穩定的最大流演算法,則可得到與容量數值無關的複雜度,例如

O(nm2).O(nm^2).

(b) 建構包含所有最短路徑的子網路 G1G_1

核心想法

要找出所有由來源 o1o_1 到目的地 d1d_1 的最短路徑,可分別計算:

  • Do[v]D_o[v]:從 o1o_1 到節點 vv 的最短距離;
  • Dd[v]D_d[v]:從節點 vv 到 d1d_1 的最短距離。

由於題目給定 cij≥0c_{ij}\ge 0,可使用 Dijkstra 演算法。

計算步驟

第一步:從來源節點計算距離

在原圖 GG 上以 o1o_1 為起點執行 Dijkstra,得到

Do[v]=dist⁡(o1,v).D_o[v]=\operatorname{dist}(o_1,v).

第二步:從目的地反向計算距離

將所有弧反向,對反向網路以 d1d_1 為起點執行 Dijkstra,得到

Dd[v]=dist⁡(v,d1).D_d[v]=\operatorname{dist}(v,d_1).

令

D=Do[d1]D=D_o[d_1]

為 o1o_1 到 d1d_1 的最短距離。

第三步:保留位於最短路徑上的弧

對每條弧 (i,j)∈A(i,j)\in A,若滿足

Do[i]+cij+Dd[j]=D,D_o[i]+c_{ij}+D_d[j]=D,

則弧 (i,j)(i,j) 位於至少一條最短路徑上,因此保留該弧。

所以子網路可定義為

A1={(i,j)∈A:Do[i]+cij+Dd[j]=D},A_1= \left\{ (i,j)\in A: D_o[i]+c_{ij}+D_d[j]=D \right\},

並令

G1=(N1,A1),G_1=(N_1,A_1),

其中 N1N_1 只包含被保留弧連接到的節點,以及來源 o1o_1 和目的地 d1d_1。

為什麼這個條件正確?

若弧 (i,j)(i,j) 位於某條最短路徑上,則該路徑必可分成三段:

o1⇝i,(i,j),j⇝d1.o_1\leadsto i,\qquad (i,j),\qquad j\leadsto d_1.

三段長度相加必須等於整體最短距離,因此

🔒

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

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

免費註冊

其他考古題