Kruskal算法和Prim算法
Kruskal
Kruskal算法是用来计算加权连通图的最小生成树的算法。
基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路。
边结构:
public static class Edge{
int begin;
int end;
int weight;
public Edge(){}
public Edge(int begin, int end, int weight){
this.begin = begin;
this.end = end;
this.weight = weight;
}
}
Kruskal
/*
*G的存储结构为邻接矩阵
*计算最小生成树
* */
public void MinSpanTree(MGraph G){
/*connect 判断加入的边是否使图构成回路*/
int[] connect = new int[G.getNumVertexes()];
/*获取图中的全部的边*/
Edge[] edges = getEdges(G.getArc(), G.getNumEdgs());
/*将边按权重从小到大排序*/
sortedEdges(edges);
/*初始化connect*/
for(int i = 0; i < connect.length; i++){
connect[i] = -1;
}
for(int i = 0; i < G.getNumEdgs(); i++){
/*如果n==m说明加入边edges[i]是图中出现回路*/
int n = find(connect, edges[i].begin);
int m = find(connect, edges[i].end);
if(n != m){
connect[n] = m;
System.out.println(edges[i].begin + " " + edges[i].end + " " + edges[i].weight);
}
}
}
/*获取全部的边*/
private Edge[] getEdges(int[][] arc, int numEdgs){
List<Edge> edges = new ArrayList<>();
Edge[] e = new Edge[numEdgs];
int count = 0;
for(int i = 1; i < arc.length; i++){
for(int j = 0; j < i; j++){
if(arc[i][j] < Integer.MAX_VALUE){
edges.add(new Edge(i, j, arc[i][j]));
count++;
}
}
}
System.out.println(count);
return edges.toArray(e);
}
/*将边按权重从小到大排序*/
private void sortedEdges(Edge[] edges){
for(int i = 0; i < edges.length - 1; i++){
for(int j = i + 1; j < edges.length; j++){
if(edges[i].weight > edges[j].weight){
Edge temp = edges[i];
edges[i] = edges[j];
edges[j] = temp;
}
}
}
}
private int find(int[] connect, int f){
while(connect[f] > -1){
f = connect[f];
}
return f;
}
Prim
Prim算法求最小生成树的时候和边数无关,和顶点树有关,所以适合求解稠密网的最小生成树。
基本思想:将图中的点分为两部分,一部分是没有访问的点集U,另一部分是访问过的点集V,然后在访问过的点集中寻找边权重最小的边的另一个节点加入。重复,直到U为空,V中包含了全部的点。
package graph;
import graph.graphadjlist.EdgeNode;
import graph.graphadjlist.GraphAdjList;
import graph.graphadjlist.VertexNode;
import java.util.ArrayList;
import java.util.List;
/*
* 图的存储结构为邻接表
* prim算法计算最小生成树
* */
public class MinSpanTreePrim {
public void getMinSpanTree(GraphAdjList<VertexNode> G) {
/*第一个节点加入到点集V*/
G.adjList.get(0).isVisited = true;
int count = 1;
/*直到全部点都访问过循环结束*/
while (count < G.numVertexes) {
int min = Integer.MAX_VALUE;
int temp = -1;
/*一次循环点集V,找到最小边的另一个点
* 加入到V中
* */
for (int i = 0; i < G.numVertexes; i++) {
if (G.adjList.get(i).isVisited == true) {
EdgeNode e = G.adjList.get(i).firstedge;
while (e != null) {
for (int j = 0; j < G.numVertexes; j++) {
if (G.adjList.get(j).data.compareTo(e.adjvex) == 0 && G.adjList.get(j).isVisited == false && e.weight < min) {
temp = j;
min = e.weight;
break;
}
}
e = e.next;
}
}
}
/*加入点G.adjList.get(temp)到点集V中*/
G.adjList.get(temp).isVisited = true;
System.out.println(G.adjList.get(temp).data);
System.out.println(min);
count++;
}
}
}