動態聯通性問題 union find演算法

2021-09-29 17:56:56 字數 1613 閱讀 9789

在給定的一張節點網路(也就是圖)中,判斷兩個節點之是否可達的問題就是連通性問題。

場景:判斷兩個使用者之間是否存在間接社交關係;判斷兩台計算機之間是否建立連線等。

使用最基本的陣列作為該演算法的資料結構。陣列下標 i 代表當前節點編號,id[i]的值表示與該節點連通的某乙個節點。每個節點id[i]的值初始化為 i。

輸入是一系列整數對,一對整數(p, q)代表p和q是相連的。

例如:輸入(3, 4)、(1,3)、(2, 5),那麼3-4、1-3、1-4、2-5是連通的。

public class uf

//union()方法只需要將乙個根節點連線到另乙個根節點即可

public void qu_union(int p,int q)

//connected()方法簡單比較find(p)和find(q)

public boolean connected(int p, int q)該演算法的特點是union快,find慢。find()方法訪問陣列次數是1+觸點所在樹的高度*2,即時間複雜度是o(logn);union()方法和connected()方法時間複雜度是常數級別o(1)。

對quick-union演算法的改進,保證小的樹鏈結在大樹上。即給每乙個連通分量新增權重,在需要將兩個連通分量合併時,將權重小的連通分量連線到大的連通分量上。

在類中新建乙個陣列儲存各根節點的權重。注意該陣列中只有根結點物件的下標中的資料有效。然後修改union方法如下:

public void union(int p, int q) else 

}

加權quick-union演算法可以有效地降低生成的連通分量的樹的高度,從而提高演算法執行效率。當然這是一種用空間換時間的方法,因為使用了輔助陣列儲存節點權重,所以它的額外空間複雜度為o(n)。

加權quick-union演算法在大部分整數對都是直接連線的情況下,生成的樹依舊會比較高。所以可以進一步優化:每次計算某個節點的根結點時,將沿路檢查的結點也指向根結點。盡可能的展平樹,這樣將大大減少find()方法遍歷的結點數目。

//union()方法

public void union(int p, int q)

}//find()方法

public int find(int p)

return p;

}//connected()方法

public boolean connected(int p, int q)

路徑壓縮後基本上連通分量樹的高度為2, 所以find()方法的時間複雜度接近o(1),union()方法的時間複雜度接近o(1)。

圖的可達性問題一般採用深度優先遍歷的思想來實現。理論上,深度優先演算法解決圖的可達性比union-find快,因為它能夠保證所需時間是線性的。

但實際上,union-find演算法更快,因為它不需要完整的構造並表示一張圖。更重要的是union-find演算法是一種動態演算法,我們在任何時候都能用接近常數的時間檢查兩個頂點是否連通,甚至在新增一條邊的時候,但深度優先演算法必須對圖進行預處理。

例項的網路聯通性問題

9月8日更新 解釋及解決辦法 解釋 openstack中有兩種ip位址的概念 fixed ip和floating ip。fixed ip 是例項的真實ip,在建立例項時注入,如果作業系統不支援注入如windows,openstack會在例項啟動後通過dhcp方式把fixed ip分配給例項。floa...

動態連通性問題

首先定義演算法的api 方法作用 uf int n 初始化觸點及其他資料 int find int p 返回p所在連通分量的識別符號 int union int p,int q 在p和q之間新增一條線 int count 返回連通分量的數量 boolean connected int p,int q...

連通性問題

1 伺服器可以ping通客戶端,說明伺服器和客戶端之間的鏈路是通的。客戶端不能ping通伺服器,很可能是防火牆的原因,包括伺服器本身自帶的防火牆和伺服器與交換機之間的cisco asa 5505防火牆。防火牆的訪問規則中清除禁止ping入之類的規則,或者清除拒絕接收icmp包的規則。2 ping不通...