这里主要讲了两个算法。
首先说明下,本文讲到的两个算法都是和连接矩阵和连接表没有关系的,因为每个算法开始的时候,都会有一个初始化代码,经过初始化后,最后都会变成统一的算法语句。
我们这里会介绍两种算法,第一种算法,Prim算法。这个算法,内容就是加点法,可以理解为在U集合周围找到权值最小的边的点,添加到U集合上,使得最后所有的点都在U集合上。
算法思想:
假设N=(V, E)是连通网,TE是N上最小生成树中边的集合。算法如下: (1)初始时,U={u},TE=φ; (2)在所有<u, v>∈E(u∈U,v∈V-U)的边中选一条代价最小的边(u, v)并入集合TE,同时将v并入U; (3)重复(2),直到U=V为止。此时,TE中必含有n-1条边,则T=(V, TE)为N的最小生成树。 可以看出,普利姆算法是逐步增加U中的顶点,称为“加点法”。 但请注意:在选择最小边时,可能有多条权值相等的边可选,此时任选其一。
代码如何实现这个Prime算法,事实上也就是四个步骤.
初始化
找到一个最小的权值的点(在哪里找?在lowCost里面找)
将其加入U集合中
修改lowCost和parent数组
我们这里分别来讲:
初始化
int sum,k;
int lowCost[vertexNum],parent[vertexNum];
k=locate(g,u);
int n=g->vertexNum;
for(int i=0;i<n;i++){
lowCost[i]=g->edge[k][i];
parent[i]=k;
}
parent[k]=-1;
lowCost[k]=0;//也就是用连接矩阵,设置好lowCost数组和parent数组
找到一个最小的权值的点
k=findMin(lowCost,n);
修改lowCost和parent数组
for(int j=0;j<n;j++){
if(g->edge[k][j]<lowCost[j] && lowCost[j]!=0){
lowCost[j]=g->edge[k][j];
parent[j]=k;
}
}
总的代码:
void Prim(Graph g,int u)
{
int sum,k;
int lowCost[vertexNum],parent[vertexNum];
k=locate(g,u);
int n=g->vertexNum;
for(int i=0;i<n;i++){
lowCost[i]=g->edge[k][i];
parent[i]=k;
}
parent[k]=-1;
lowCost[k]=0;
sum=0;
for(int i=1;i<n;i++){//注意是查询n-1次。
k=findMin(lowCost,n);//这个函数就是一个简单的从一个数组中找到最小的值,所在的下标,并且返回回来。
if(k==-1){
return ;
}
sum=sum+lowCost[k];
lowCost[k]=0;
for(int j=0;j<n;j++){
if(g->edge[k][j]<lowCost[j] && lowCost[j]!=0){
lowCost[j]=g->edge[k][j];
parent[j]=k;
}
}
}
return sum;
}
Krus算法,其实这个也就是一个并查集算法,我这里先把代码放出来。
void Krus(Graph g)
{
int i,j,n;
Edge edges[vertexNum*vertexNum];
sort(edges);
for(int i=0;i<g->edges;i++){
n=find(edges[i].begin);
m=find(edges[i].end);
if(n!=m){
parent[n]=m;
}
}
}
其中的find函数在这里
int find(int parent[],int x)
{
while(parent[x]!=x){
x=parent[x];
}
return x;
}
先写到这里,以后来完善