prim算法(破圈法)
kruskal算法(避圈法)
基本思想:
设G=(V,E)是网络,最小生成树的初始状态为只有VN个顶点而无边的非联通图T,T中每个顶点自成一个连通图。将集合E中的边按权递增顺序排列,选择 两个顶点分别在不通风的连通图且权最小的 边加入图T,则原来的两个连通图成为一个连通图。以此类推,知道T中所有的顶点都在同一个连通图中为止,该连通图就是所求的最小生成树。处理过程中加入边时避免产生回路,所以该算法也称避圈法。
储存结构:
1.图采用邻接矩阵表示。
2.mst数组类型为Edge,包括边的起点、终点和权。算法结束后,mst存放求出的最小生成树的VN-1条边。
3.用一个整型数组status[0...VN-1]记录各个顶点所属的连通子图,每个连通子图用一个顶点的下表表示。
代码实现:
#include <iostream>
#define AdjType int
#define VN 6
#define MAX 1000
using namespace std;
struct GraphMatrix
{
AdjType arc[VN][VN];
};
typedef struct{
int start,stop;
AdjType weight;
}Edge;
Edge mst[VN-1];
void kruskal(GraphMatrix* Pgraph,Edge *mst)
{
int num=0,x,y,minWeight,status[VN];
for(int i=0;i<VN;i++)
status[i]=i;//每个顶点属于自己代表的连通子图
while(num<VN-1){
minWeight=MAX;
for(int i=0;i<VN-1;i++)//找到最短边
for(int j=i+1;j<VN;j++){
if(Pgraph->arc[i][j]<minWeight){
x=i;y=j;minWeight=Pgraph->arc[i][j];
}
}
if(minWeight==MAX){
cout<<"No MST!\n";
return ;
}
if(status[x]!=status[y]){//不属于同一连通子图
mst[num].start=x;
mst[num].stop=y;
mst[num].weight=minWeight;
num++;
int j=status[y]; //原来statu[y]代表的连通子图的结点,现都属于status[x]代表的连通子图
for(int i=0;i<VN;i++)
if(status[i]==j)
status[i]=status[x];
}
Pgraph->arc[y][x]=Pgraph->arc[x][y]=MAX;//删除已加入T的最短边
}
cout<<"Edges(start_ver,stop_vex,weight) of MST:\n";
for(int i=0;i<VN-1;i++)
cout<<"("<<mst[i].start<<","<<mst[i].stop<<","<<mst[i].weight<<")\n";
}
int main()
{
GraphMatrix *G=new struct GraphMatrix;
for(int i=0;i<VN;i++)
for(int j=0;j<VN;j++)
cin>>G->arc[i][j];
kruskal(G,mst);
return 0;
}
时间复杂度为O(n^3)。
Input
0 10 1000 1000 19 21
10 0 5 6 1000 11
1000 5 0 6 1000 1000
1000 6 6 0 18 14
19 1000 1000 18 0 33
21 11 1000 14 33 0
Output
Edges(start_ver,stop_vex,weight) of MST:
(1,2,5)
(1,3,6)
(0,1,10)
(1,5,11)
(3,4,18)