圖的表示法與廣度優先搜尋 (Graph Representations and BFS)

重點總覽 (Overview)

項目 重點 一句話
Graph vertices(實體) + edges(關係) 本章只談 directional edge;雙向關係用兩條方向邊表示
Adjacency matrix A[i][j]=1 代表有 i→j 直覺但 O(N²) 儲存,稀疏圖極度浪費
Sparsely connected 平均 degree ≪ N−1 真實圖(社群網路、道路網)幾乎都稀疏 → 用稀疏格式
CSR srcPtrs + dst 快速取得某 source 的 outgoing edges(列)
CSC dstPtrs + src 快速取得某 destination 的 incoming edges(行)
COO src + dst(每邊一筆) 由 edge 直接取得 source/dst,最易暴露平行度
BFS 由 root 逐層 label hop 數 找「最少邊數」最短路徑;形成 wavefront / BFS tree
應用 maze routing(IC 繞線) wiring block = vertex,可繞 = edge,BFS 找最短繞線
Important

格式選擇 = 演算法選擇。CSR↔push/top-down、CSC↔pull/bottom-up、COO↔edge-centric。這條對應關係貫穿整章,詳見 15-Graph-Traversal/02-Vertex-Centric-and-Edge-Centric-BFS


圖與相鄰矩陣 (Graph & Adjacency Matrix)

本章範例(Fig. 15.1):9 vertices、15 directional edges。

        dst →  0  1  2  3  4  5  6  7  8     row sum (out-degree)
 src ↓
   0           .  1  1  .  .  .  .  .  .        2     0→1, 0→2
   1           .  .  .  1  1  .  .  .  .        2     1→3, 1→4
   2           .  .  .  .  .  1  1  1  .        3     2→5, 2→6, 2→7
   3           .  .  .  .  1  .  .  .  1        2     3→4, 3→8
   4           .  .  .  .  .  1  .  .  1        2     4→5, 4→8
   5           .  .  .  .  .  .  1  .  .        1     5→6
   6           .  .  .  .  .  .  .  .  1        1     6→8
   7           1  .  .  .  .  .  1  .  .        2     7→0, 7→6
   8           .  .  .  .  .  .  .  .  .        0

稀疏 vs. 全連接 (Sparse vs. Fully Connected)

概念 公式 / 數值 說明
全連接 out-degree N − 1 每點連到所有其他點(無自環)
全連接總邊數 N(N−1) 9 點 → 9×8 = 72
本範例 15 邊,max out-degree = 3 sparsely connected:平均 degree ≪ N−1
Adjacency matrix 儲存 = = 81 多數元素為 0,浪費
Tip

稀疏圖 = 稀疏矩陣。直接沿用 14-Sparse-Matrix-Computation/01-Sparse-Matrices-and-Basic-Formats-COO-CSR 的壓縮格式,大幅省儲存與省掉對 0 元素的無用運算。


稀疏儲存格式 CSR / CSC / COO (Sparse Storage Formats)

命名約定(本章專用):索引/指標稱 src / srcPtrs;索引/指標稱 dst / dstPtrs。因為矩陣的「列 = source vertex、行 = destination vertex」。

CSR (Compressed Sparse Row) — 按 source 分組

srcPtrs[v] = vertex v 的 outgoing edges 起始位置 → 快速取得出邊

srcPtrs : [ 0  2  4  7  9 11 12 13 15 15 ]   (長度 N+1 = 10)
            v0 v1 v2 v3 v4 v5 v6 v7 v8 end
dst     : [ 1  2 | 3  4 | 5  6  7 | 4  8 | 5  8 | 6 | 8 | 0  6 ]   (長度 E = 15)
 index    0  1   2  3    4  5  6   7  8   9 10  11  12  13 14

CSC (Compressed Sparse Column) — 按 destination 分組

dstPtrs[v] = vertex v 的 incoming edges 起始位置 → 快速取得入邊(predecessors)。

dstPtrs : [ 0  1  2  3  4  6  8 11 12 15 ]
src     : [ 7 | 0 | 0 | 1 | 1  3 | 2  4 | 2  5  7 | 2 | 3  4  6 ]
            ↑v0  ↑v1 ↑v2 ↑v3  ↑v4    ↑v5     ↑v6   ↑v7   ↑v8

COO (Coordinate) — 每邊一筆 (src, dst)

src : [ 0 0 1 1 2 2 2 3 3 4 4 5 6 7 7 ]
dst : [ 1 2 3 4 5 6 7 4 8 5 8 6 8 0 6 ]   ← 第 k 筆 = 邊 src[k]→dst[k]

格式對照 (Format Comparison)

格式 易取得 對應 BFS 方向 儲存量(本例) 適用
CSR 某點的 outgoing edges(列) push / top-down (N+1)+E = 10+15 = 25 low-degree、early levels
CSC 某點的 incoming edges(行) pull / bottom-up (N+1)+E = 25 later levels、找 predecessor
COO edge 的 src 與 dst edge-centric 2E = 30 小圖 / 高 degree 變異大
Tip

data array 可省略:本例所有非零值都是 1,「邊存在」本身即代表 1,不必存 data。但若邊帶權重(距離、建立日期),data 就必須顯式儲存。

公式(CSR 省儲存比):

adjacency matrix 儲存 = N²                    = 81
CSR 儲存(無 data)    = (N+1) + E             = 25
real-world(極稀疏) → 節省可達數個數量級
Warning

無向圖(undirected,adjacency matrix 對稱)時 CSR 與 CSC 等價,只需存一份即可同時供 push/pull 使用;有向圖若要做 direction-optimized 則 CSR、CSC 兩份都要存。


廣度優先搜尋 (Breadth-First Search, BFS)

Level labeling = wavefront(以 root = 0)

Level 0 :  0                         (root)
Level 1 :  1   2                     經 1 條邊:0→1, 0→2
Level 2 :  3   4   5   6   7         3,4 ← via 1 ; 5,6,7 ← via 2
Level 3 :  8                         8 ← via 3 或 4 或 6

root 換成 2,結果差很多(雖只差 1 條邊):L1={5,6,7}、L2={8(via 6), 0(via 7)}、L3={1(via 0)}、L4={3,4(via 1)}。root 不同 → BFS 結果截然不同

BFS tree 與最短路徑回溯 (BFS Tree & Path Backtrace)

sequential BFS level-labeling (概念,平行版見 sibling notes)
level[root] = 0; 其餘 = INF
for L = 0, 1, 2, ...:
    for each v with level[v] == L:
        for each neighbor u of v (via outgoing edge):
            if level[u] == INF:   level[u] = L + 1
    若本輪無新 label → 結束

path backtrace (需 incoming edges / CSC):
cur = target
while cur != root:
    pick predecessor p of cur with level[p] == level[cur] - 1
    output edge p→cur ; cur = p
Warning

回溯需要每個 vertex 的「入邊 source 清單」才找得到 predecessors → 這正是 CSC 提供的存取方式。push/CSR 只給出邊,無法直接回溯。

複雜度:

BFS 走訪每個 vertex 一次、每條 edge 一次 → O(V + E)

應用:Maze Routing(IC 繞線)

對應 圖元素
晶片切成 wiring blocks 網格 每個 block = vertex
可往水平/垂直延伸成線 block 之間的 edge
block 被元件或既有線佔用 標為 blockage vertex 或移出圖
maze wavefront from root R (上下左右擴張)
              · 3 ·            level 1 : 4  個 (R 的四鄰)
            3 2 1 2 3          level 2 : 8  個
            · 1 R 1 ·          level 3 : 12 個
            3 2 1 2 3          ...      逐層 +4 (空曠時)
              · 3 ·
Important

Maze routing 圖通常 undirected(adjacency matrix 對稱)→ CSR/CSC 等價,只需存一份。


考試/面試重點 (Exam / Test Patterns)

情境 / 關鍵字 答案 / 技巧
「全連接有向圖共幾條邊?」 N(N−1)(無自環);每點 out-degree = N−1
「sparsely connected 定義」 平均 out-degree ≪ N−1 → 適合稀疏格式
「要快速拿某點的出邊 → 用哪種格式?」 CSR(srcPtrs+dst),對應 push/top-down
「要快速拿某點的入邊 / 找 predecessor?」 CSC(dstPtrs+src),對應 pull/bottom-up + 路徑回溯
「由一條 edge 直接拿 src 與 dst?」 COO(src+dst 配對),對應 edge-centric
srcPtrs[i] 是什麼?」 vertex i 的出邊在 dst[]起始 index;srcPtrs[i+1]−srcPtrs[i] = out-degree
「CSR 省多少儲存?」 (N+1)+E vs ;本例 25 vs 81(data 全為 1 可省)
「何時 data 不能省?」 邊帶權重(距離、權值、日期)時必須顯式存
「BFS label 代表什麼?」 root 到該點的最少邊數(level/depth) = 最短 hop 數
「BFS 複雜度?」 O(V+E)
「換 root 結果會變嗎?」 會,而且差異可能很大(即使新 root 只差 1 邊)
「如何回溯最短路徑?」 從 target 往回挑 level 比自己小 1 的 predecessor(需 incoming/CSC);多 predecessor = 多條等長解
「無向圖能省什麼?」 adjacency matrix 對稱 → CSR 與 CSC 等價,只存一份
「maze routing 怎麼映射成圖?」 wiring block = vertex,可延伸 = edge,blockage 移除/標記;BFS wavefront 找最短繞線