因为不是经常用到这些算法,这里写一下自己的理解。待日后用到的时候可以重新看一下。
Prim算法,主要是将各个点分到S集合,U集合。S集合是已经都确定最短路径的,U集合是未确定的。(这里通过将)
首先将与起始点相连的各个点装到lowcost里面,并将起始点到达该点的前一个点装入closest里(供查找路径使用)。
然后循环剩下的n-1个点,找出与起始点最近的一个点k。
然后更新lowcost与closest(将k点到达的i点的距离与起始点直接到达i点的距离比较,是否经过k点距离更近?如果是,closest[i] = k ,起始点到达i点前一个点是点k)
public class Prim {
private MGraph g;
private final int INF = 32767;
private final int MAX = 100;
public Prim(MGraph g){
this.g = g;
}
private class MGraph{
private int[][] edges;//点到点的距离
private int n;//总共多少个点
}
void Make_MSP(int v){
int lowcost[] = new int[MAX];//保存 与已经描绘出的路径中各个点最近的 距离
int closest[] = new int[MAX];//保存 最近的距离是由已经描绘出的路径中的哪个顶点最为媒介搭桥的
int min,k = 0;
for(int i = 0 ; i < g.n ; i ++){//初始化lowcost、closest
lowcost[i] = g.edges[v][i];
closest[i] = v;
}
for(int i = 1 ; i < g.n ; i ++){
min = INF;
for(int j = 0 ; j < g.n ; j++){//得出v点到其他点中最短路径的点
if(lowcost[j] != 0 && lowcost[j] < min){
min = lowcost[j];
k = j;
}
}
lowcost[k] = 0;//标记K已经加入U。
for(int j = 0 ; j < g.n ; j ++){
if(g.edges[k][j] != 0 && g.edges[k][j] < lowcost[j]){
closest[j] = k;
lowcost[j] = g.edges[k][j];
}
}
}
}
}
Kruscal:
克鲁斯科尔算法用于 边少,点多的时候。
主要的思想:将点与点之间距离短的从小到大连接起来,前提他们不会构成一个回路(这里是通过判断该点是否在同一个集合里来判断的是否构成回路,用了vset数组),就ok了
public class Kruskal {
private final int INF = 32767;
private final int MAX = 100;
private class MGraph{
private int n;
private int[][] edges;
}
void Make_MSP(MGraph g){
Edge[] E = new Edge[MAX];
int k = 0,u1,v1,sn1,sn2;
int vset[] = new int[MAX];//辅助数组
for(int i = 0 ; i < g.n ; i ++){
for(int j = 0 ; j < g.n ; j ++){
if (g.edges[i][j] != 0 && g.edges[i][j] != INF) {
E[k] = new Edge();
E[k].u = i;
E[k].v = j;
E[k].w = g.edges[i][j];
k++;
}
}
}
InsertSort ise = new InsertSort();
ise.Sort(E);//插入排序,将点与点的距离按从小到大排序
for(int i = 0 ; i < g.n ; i ++){
vset[i] = i;
}
k = 1;
int j = 0;
while(k < g.n){
u1 = E[j].u;
v1 = E[j].v;
sn1 = vset[u1];
sn2 = vset[v1];
if (sn1 != sn2) {
k++;
for(int i = 0 ; i < g.n ; i ++){
if (vset[i] == sn2) {
vset[i] = sn1;
}
}
}
j++;
}
}
}