演算法導論22.1圖的表示 練習總結
22.1-1 給定有向圖的鄰接連結串列,需要多長時間才能計算出每個結點的出度(發出的邊的條數)?多長時間才能計算出每個結點的入度(進入的邊的條數)?
ANSWER:① 出度:O(V+E),因為計算 n 個結點的連結串列長度為 O(n),所以需要計算 O(V) 個連結串列長度時間為 O(V+E)。② 入度:O(V+E),同理。
22.1-2 給定一棵有 7 個結點的完全二叉樹的鄰接連結串列,請給出等價的鄰接矩陣表示。這裡假設結點的編號為從 1~7。
ANSWER:
22.1-3 有向圖 G = (V,E) 的轉置是圖 G^T = (V,E^T),這裡 E^T = {(v,u) ∈ V * V : (u,v) ∈ E}。因此,圖 G^T 就是將有向圖 G 中所有邊的方向反過來而形成的圖。對於鄰接連結串列和鄰接矩陣兩種表示方法,請給出從圖G 計算出 G^T 的有效演算法,並分析演算法的執行時間。
ANSWER:
鄰接連結串列:用 O(V+E) 時間遍歷連結串列,獲取所有結點。對結點為 i 的連結串列,將結點 i 放在以該連結串列的陣列 Adj 為結點的連結串列中;時間為 O(V+E)。
鄰接矩陣:返回原矩陣的轉置,時間為 O(V^2)。
22.1-4 給定多圖 G = (V,E) 的鄰接連結串列(多圖允許重複邊和自迴圈邊的圖),請給出一個時間為 O(V+E) 的演算法,用來計算該圖的“等價”無向圖 G‘ = (V,E') 的鄰接連結串列表示。這裡 E' 是將 E 中的冗餘邊和自迴圈邊刪除後餘下的邊。刪除冗餘邊指的是將兩個節點之間的多條邊替換為一條邊。
ANSWER:遍歷多圖 G 的每個連結串列,並複製連結串列;若連結串列的 Adj 元素與連結串列頭節點重複,則不復制該元素;若連結串列中 Adj 元素重複多次出現,則只複製一次。複製完成後,新的鄰接連結串列若出現只有頭結點的連結串列,則刪除該連結串列。
22.1-5 有向圖 G = (V,E) 的平方圖是圖 G2 = (V,E2),這裡,邊 (u, v) ∈ E2 當且僅當圖 G 包含一條最多由兩條邊構成的從 u 到 v 的路徑。請給出一個有效演算法來計算圖 G 的平方圖 G2。這裡圖 G 既可以以鄰接連結串列表示,也可以以鄰接矩陣表示。請分析演算法的執行時間。
ANSWER:鄰接矩陣,時間複雜度:O(V^3)。
for i = 1 to n for j = 1 to n if G[i][j] == 1 G2[i][j] = 1 else for k = 1 to n if G[i][k] == 1 and G[k][j] == 1 G2[i][j] = 1 else G2[i][j] = 0
22.1-6 多數以鄰接矩陣作為輸入的圖演算法的執行時間為 Ω(V^2),但也有例外。給定圖 G 的鄰接矩陣表示,請給出一個 O(V) 時間的演算法來判斷有向圖 G 是否存在一個通用匯點。通用匯點指的是入度為 |V| - 1 但出度為 0 的結點。
ANSWER:若結點 i 滿足題意,則在鄰接矩陣中,第 i 行全為 0,第 i 列全為 1(第 i 行第 i 列除外)。
按結點編號由大到小(從鄰接矩陣右下角向左上方向)檢測,當檢測結點 i 時,若結點 x 與結點 i 的關係滿足題意(即 x 指向 i,i 不指向 x),則 x 一定不滿足題意。所以,向上檢測某結點的同時,也在檢測其它結點。執行一次 while 迴圈後篩選出唯一一個可能成立的 ans 值,再用 O(V) 時間檢測其是否成立。
虛擬碼:
SEARCH_USPOINT(G):
i = v
j = 1
while i - j > 0
ans = v
if G[i][i-j] == 0 and G[i-j][i] == 1 //結點入度加 1,出度為 0
j = j + 1
else //檢測下一結點
i = i - j
ans = i
j = 1
if CHECK(ans)
return true
else
return false
CHECK(ans):
for i = 1 to V
if G[i][ans] != 1 or G[ans][i] != 0
return false
else
return true</span>
22.1-7 有向無環圖 G = (V, E) 的關聯矩陣是一個滿足下述條件的 |V| * |E| 矩陣 B = (bij):
bij = -1 (如果邊 j 從結點 i 發出);1 (如果邊 j 進入結點 i);0 (其他)。
請說明矩陣乘積 B*B^T 裡的每一個元素代表什麼意思。這裡 B^T 是矩陣 B 的轉置。
ANSWER:
當 i = j 時,B*B^T(i, j) = i 的入度 + i 的出度。
當 i ≠ j 時,B*B^T(i, j) = (i → k → j) 邊數 + (i ← k ← j) 邊數 - (i ← k → j) 邊數 - (i → k ← j)邊數;k ∈[1, V]。
22.1-8 假定陣列 Adj[u] 的每個記錄項不是連結串列,而是一個散列表,裡面包含的是 (u, v) ∈ E 的結點 v。如果每條邊被查詢的概率相同,則判斷一條邊是否在圖中的期望時間值是多少?這種表示方式的缺陷是什麼?請為每條邊連結串列給出一個不同的資料結構來解決這個問題。與散列表相比較,你所給出的新方法存在什麼缺陷嗎?
ANSWER:
① 搜尋期望時間為 O(1),先找到 Adj[u],然後用 O(1) 時間在 u 中找到 v。
② 缺陷:會比鄰接連結串列使用更多空間。
③ 利用二叉搜尋樹存放每條邊連結串列的值。
④ 新方法缺陷:搜尋時間會變成 O(lgn),n 為二叉樹大小。