在普里姆算法中,我们从一些根顶点开始的单个集群生成一颗最小生成树,主要思想与Dijkstra算法一些,属于贪心算法
算法思想
我们先初始定义一个顶点,然后在相邻的所有边中迭代算这一个最小权值的边 e = (u,v),将顶点u链接到初始点c之外的顶点v,之后将顶点v放到c中,并且一直重复知道完成,
算法分析
prim算法与dijksta类似,都比较依赖与一个适应性比较强的优先队列Q,我们最初将n放到q中,然后在取出操作,并且更新全部m的优先权作为算法的一部分,这些都是主要花费的世界,如果是一个基于堆的优先对立,每个操作的运行时间是O(log n),全部则是O((n+m)Log n),对于连图是O(m log n),未排序的则是O(n^2)
算法步骤
-
设G-(V,E)是连通网, T-(U,D)是最小生成树, v,U是顶点集合, E,D是边的集合
-
若从顶点u开始构造最小生成树,则从集合v中取出顶点u放入集合U中,标记顶点v的visited[u]-1
-
若集合U中顶点ui与集合v-U中的顶点vi之间存在边,则寻找这些边中权值最小的边,但不能构成回路,将顶点vj加入集合U中,将边(ui,vj)加入集合D中,标记visited[vij]-1
-
重复步骤2,直到U与v相等,即所有顶点都被标记为访问过,此时D中有n-1条边
-
提示:单独看步骤很难理解,我们通过代码来讲解,比较好理解
图解步骤
顶点a的领边是 a->b = 5, a->g = 2, a->c = 7,选择g
集合U有a->b = 5, a->c = 7,g->b = 3,g -> e = 4,故算g->b
g->b 已经访问过b了,a->b就没有了,集合U有,a->c = 7,b->d = 9,g -> e = 4,故算g->e
集合U有 a->c = 7, b->d = 9,e->f = 5,故算e - > f
集合U有 a->c = 7, b->d = 9,f ->d = 4,故算f->d
集合U有 a->c = 7, b->d = 9, e->c =8 故算a - >c
代码
public void prim(MGraph graph, int v){
int visited[] = new int[graph.graphNodeCount];
visited[v] = 1;
int top1 = -1, top2 = -1;
int minWeight = 10000; // 最大权值
for(int k = 0;k < graph.graphNodeCount;k++){
for (int i = 0; i < graph.graphNodeCount; i++) {
for (int j = 0; j < graph.graphNodeCount; j++) {
if (visited[i] == 1 && visited[j] == 0 && graph.weight[i][j] < minWeight) {
minWeight = graph.weight[i][j]; //替换最小权重
top1 = i;
top2 = j;
}
}
}
visited[top2] = 1;
minWeight = 10000;
}
}