1. 程式人生 > >演算法導論22.1圖的表示 練習總結

演算法導論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 為二叉樹大小。