最小生成树Prim算法Java版
算法描述:
- 在一个加权连通图中,顶点集合V,边集合为E
- 任意选出一个点作为初始顶点,标记为visit,计算所有与之相连接的点的距离,选择距离最短的,标记visit.
- 重复以下操作,直到所有点都被标记为visit:
在剩下的点钟,计算与已标记visit点距离最小的点,标记visit,证明加入了最小生成树。
对比克鲁斯卡尔算法
假设网中有n个节点和e条边,普利姆算法的时间复杂度是O(n^2),克鲁斯卡尔算法的时间复杂度是O(eloge),可以看出前者与网中的边数无关,而后者相反。因此,普利姆算法适用于边稠密的网络而克鲁斯卡尔算法适用于求解边稀疏的网。
克鲁斯卡尔算法的时间复杂度主要由排序方法决定,而克鲁斯卡尔算法的排序方法只与网中边的条数有关,而与网中顶点的个数无关,当使用时间复杂度为O(elog2e)的排序方法时,克鲁斯卡尔算法的时间复杂度即为O(log2e),因此当网的顶点个数较多、而边的条数较少时,使用克鲁斯卡尔算法构造最小生成树效果较好
Code
package com.company;
import java.util.*;
public class MinTree {
public static void main(String[] args) {
int[][] arr = new int[][]{
// 0 1 2 3 4 5 6 7 8
{-0, 4, 0, 0, 0, 0, 0, 7, 0},
{4, -0, 8, 0, 0, 0, 0, 11, 0},
{0, 8, -0, 7, 0, 4, 0, 0, 2},
{0, 0, 7, -0, 9, 14, 0, 0, 0},
{0, 0, 0, 9, -0, 10, 0, 0, 0},
{0, 0, 4, 14, 10, -0, 2, 0, 0},
{0, 0, 0, 0, 0, 2, -0, 1, 6},
{7, 11, 0, 0, 0, 0, 1, -0, 7},
{0, 0, 2, 0, 0, 0, 6, 7,-0}
};
boolean[] visited=new boolean[arr.length];
visited[0]=true;
PriorityQueue<Integer[]> queue=new PriorityQueue<>(new Comparator<Integer[]>() {
@Override
public int compare(Integer[] o1, Integer[] o2) {
return o1[0]-o2[0];
}
});
int count=1;
for (int i = 0; i < arr.length; i++) {
if(arr[0][i]!=0&&!visited[i]){
queue.add(new Integer[]{arr[0][i],0,i});
}
}
while (count<arr.length){
Integer[] temp=null;
while (!queue.isEmpty()){
temp=queue.poll();
if(visited[temp[2]])continue;
break;
}
visited[temp[2]]=true;
System.out.println("起点:"+temp[1]+" 终点:"+temp[2]+" 长度为:"+temp[0]);
for (int i = 0; i < arr.length; i++) {
if(arr[temp[2]][i]!=0&&!visited[i]){
queue.add(new Integer[]{arr[temp[2]][i],temp[2],i});
}
}
count++;
}
}
}
输出
起点:0 终点:1 长度为:4
起点:0 终点:7 长度为:7
起点:7 终点:6 长度为:1
起点:6 终点:5 长度为:2
起点:5 终点:2 长度为:4
起点:2 终点:8 长度为:2
起点:2 终点:3 长度为:7
起点:3 终点:4 长度为:9
Process finished with exit code 0