java演算法例項_合併元素&&判斷元素是否連通
阿新 • • 發佈:2018-12-13
案例1:簡單的實現方式,直接遍歷
程式碼:
package me.ele.union_find; import java.util.Arrays; import java.util.List; /** * 快速查詢 UC(union find) * <p> * 有一些元素 a b c d e f g h ...... * * @author LZJ * @create 2018-10-03 13:40 **/ public class QuickFindUF { private int[] idArr; /** * 初始化 陣列,陣列中每個位置上元素的值 即 元素的下標 * * @param n */ public QuickFindUF(int n) { idArr = new int[n]; for (int i = 0; i < n; i++) { idArr[i] = i; } } /** * 給定兩個元素,查詢兩個元素是否在統一集合內 * * @param p * @param q * @return 如果兩個元素在陣列中的值 相等,即代表兩個元素連通 */ public boolean find(int p, int q) { return idArr[p] == idArr[q]; } /** * 合併兩個元素 即 將兩個元素連通 * 每次合併 兩個元素的時候,遍歷當前陣列,將其中所有符合(值與p元素的值相等的)所有元素 替換為q的值 * 這樣,p元素以及之前的符合條件的元素 都會與q元素合併(連通) * * @param p * @param q */ public void union(int p, int q) { int length = idArr.length; for (int i = 0; i < length; i++) { if (idArr[i] == idArr[p]) { idArr[i] = idArr[q]; } } } }
測試:
public static void main(String[] args) { // [0-9]十個元素放置到陣列 idArr 之所以使用0-9不重複的數字 是因為想要唯一區分每個元素 QuickFindUF quickFindUF = new QuickFindUF(10); System.out.println("------- 合併(連通)元素:1和2 -------"); quickFindUF.union(1, 2); System.out.println("合併後å陣列id:" + Arrays.toString(quickFindUF.idArr)); System.out.println("------- 合併(連通)元素:2和3 -------"); quickFindUF.union(2, 3); System.out.println("陣列id:" + Arrays.toString(quickFindUF.idArr)); System.out.println("------- 合併(連通)元素:4和5 -------"); quickFindUF.union(4, 5); System.out.println("陣列id:" + Arrays.toString(quickFindUF.idArr)); System.out.println("========"); System.out.println("元素:1和2是否連通-->" + quickFindUF.find(1, 2)); System.out.println("元素:1和4是否連通-->" + quickFindUF.find(1, 4)); System.out.println("元素:4和5是否連通-->" + quickFindUF.find(4, 5)); }
執行結果:
案例2:通過 根的方式區分元素是否在同一集合
程式碼:
package me.ele.union_find; import java.util.Arrays; /** * 上一個 QuickFindUF演算法 合併元素的時候,將所有元素的直接連在一起 * 在本QuickUnionUF中,將會區分root節點 root節點一致的兩個元素是連通的 * * @author LZJ * @create 2018-10-03 14:29 **/ public class QuickUnionUF { private int[] idArr; public QuickUnionUF(int n) { idArr = new int[n]; for (int i = 0; i < n; i++) { idArr[i] = i; } } public int root(int p) { while (idArr[p] != p) { p = idArr[p]; } return p; } public void union(int p, int q) { int root_p = root(p); int root_q = root(q); idArr[root_p] = root_q; } public boolean find(int p, int q) { return root(p) == root(q); } }
測試:
public static void main(String[] args) {
QuickUnionUF quickUnionUF = new QuickUnionUF(10);
System.out.println(Arrays.toString(quickUnionUF.idArr));
System.out.println("------- 合併1 和 2:-------");
quickUnionUF.union(1, 2);
System.out.println(Arrays.toString(quickUnionUF.idArr));
System.out.println("判斷 1 和2 是否連通:");
System.out.println(quickUnionUF.find(1, 2));
System.out.println("------- 合併2 和 4:-------");
quickUnionUF.union(2, 4);
System.out.println(Arrays.toString(quickUnionUF.idArr));
System.out.println("判斷 2 和4 是否連通:");
System.out.println(quickUnionUF.find(2, 4));
System.out.println("1 的根:" + quickUnionUF.root(1));
System.out.println("判斷 1 和4 是否連通:");
System.out.println(quickUnionUF.find(1, 4));
}
執行結果:
案例3: 在案例2的基礎上新增權重
程式碼:
package me.ele.union_find;
import java.util.Arrays;
/**
* 有root並且 帶權重的 合併
* @author LZJ
* @create 2018-10-03 14:46
**/
public class WeightUnionUF {
int[] idArr;
int[] weight;
public WeightUnionUF(int n) {
idArr = new int[n];
weight = new int[n];
for (int i = 0; i < n; i++) {
idArr[i] = i;
weight[i] = 1;
}
}
private int root(int p) {
while (idArr[p] != p) {
idArr[p] = idArr[idArr[p]];
p = idArr[p];
}
return p;
}
public void union(int p, int q) {
int root_p = root(p);
int root_q = root(q);
if (weight[root_q] >= weight[root_p]) {
idArr[root_p] = root_q;
weight[root_q] += weight[root_p];
weight[root_p] = 0;
} else {
idArr[root_q] = root_p;
weight[root_p] += weight[root_q];
weight[root_q] = 0;
}
}
public boolean find(int p, int q) {
return root(p) == root(q);
}
}
測試:
public static void main(String[] args) {
WeightUnionUF weightUnionUF = new WeightUnionUF(10);
System.out.println("idArr:"+ Arrays.toString(weightUnionUF.idArr));
System.out.println("weight:"+ Arrays.toString(weightUnionUF.weight));
System.out.println("-----合併 1 和 3-----");
weightUnionUF.union(1,3);
System.out.println("idArr:"+ Arrays.toString(weightUnionUF.idArr));
System.out.println("weight:"+ Arrays.toString(weightUnionUF.weight));
System.out.println("1 和 3是否連通:"+weightUnionUF.find(1,3));
System.out.println("-----合併 1 和 4-----");
weightUnionUF.union(1,4);
System.out.println("idArr:"+ Arrays.toString(weightUnionUF.idArr));
System.out.println("weight:"+ Arrays.toString(weightUnionUF.weight));
System.out.println("1 和 3是否連通:"+weightUnionUF.find(1,3));
System.out.println("1 和 4是否連通:"+weightUnionUF.find(1,4));
System.out.println("3 和 4是否連通:"+weightUnionUF.find(3,4));
System.out.println("-----合併 3 和 4-----");
weightUnionUF.union(3,4);
System.out.println("idArr:"+ Arrays.toString(weightUnionUF.idArr));
System.out.println("weight:"+ Arrays.toString(weightUnionUF.weight));
System.out.println("1 和 3是否連通:"+weightUnionUF.find(1,3));
System.out.println("1 和 4是否連通:"+weightUnionUF.find(1,4));
System.out.println("3 和 4是否連通:"+weightUnionUF.find(3,4));
}
執行結果: