这个是通过考察顶点的关系来生成最小树的:
- 首先选取任意的一个顶点来做当前树的第一个顶点。
- 考察图中剩下的其他顶点与当前树的距离,选取距离最短的一个顶点加入当前树中。
- 重复上一步,直到所有的顶点已经加入到树中。
关键是怎么考察图中其他顶点与树的距离,这里树的距离是我自己定义的,就是当前顶点Vi的所有边中可以与树中顶点连接的边,其中权值即距离最小的边就是加入Vi到树中要选取的路径。
我们可以声明两个数组一个数组是weightSign用来表示当前所以可与树链接的边的权值,weightSign[k]表示编号为k的顶点Vk与树的最短边的权值(如果weightSign[k]=0,那么说明Vk就在树中了,如果weightSign[k]=∞,说明Vk不能加入到树中)。我们还需要知道Vk顶点与树中的哪个顶点可以连接,还需要另外一个数组vertexSign,vertexSign[k]就表示Vk与当前树中的顶点V(vertexSign[k])的距离最短。
可以得知weightSign数组的大小与图中顶点的数目相同,vertexSign与weightSign长度相同。假设树中已经有n个顶点了,下面考虑如何将选取第n+1个顶点。由于weightSign[k]表示编号为k的顶点与树的距离,我们找到距离最小的一个点,就可以了,那么新加入树的边为(k,vertexSign[k]),权重为weightSign[k]。函数FindMiniWeight()实现了这个功能
int FindMiniWeight(Mgraph* G,int *wightSign)
{
int k;
int min=INFINITY;
for (int j=0;j<G->numVertexs;j++)
{
if (wightSign[j]!=0&&wightSign[j]<min)
{
min=wightSign[j];
k=j;
}
}
return k;
}
下面讲述如何将顶点Vk的信息加入到树中。
- 首先更新weightSign[k]=0,表示Vk已经在树中了。
- 从第0个顶点开始,遍历与Vk的距离,比较是与Vk的距离短还是与树的距离短(去掉当前顶点已经在树中的情况)。例如顶点Vm,与树的距离为(m,vertexSign[m]),权重为weightSign[m],比较weightSign[m]与(Vm,Vk)的值。
- 如果(Vm,Vk)的值较小那么就需要更新数组weightSign和vertexSign的值了,将vertexSign[m]的值更新为Vk,表示由于树新加入了顶点Vk,顶点Vm与Vk的距离更短,weightSign[m]更新为(Vm,Vk)的值。
- 循环遍历所有的顶点,直到所有的顶点与Vk的距离都比较完成。
函数AddTree()实现了下列功能:
void AddTree(Mgraph* G,int* vertexSign,int* wightSign,int vertexNum)
{
wightSign[vertexNum]=0;
for (int j=0;j<G->numVertexs;j++)
{
if (wightSign[j]!=0&&G->arc[vertexNum][j]<wightSign[j])
{
wightSign[j]=G->arc[vertexNum][j];
vertexSign[j]=vertexNum;
}
}
}
首先开始的时候,我们需要选取一个顶点加入树中,比如V0,然后每次循环就寻找一个合适的顶点加入到树中,一共循环N次就把N个顶点全部加入到树中了。下面是代码
void MiniSpanTreePrim(Mgraph *G)
{
//存放新加入树的结点与树中各节点的距离。
int *vertexSign=(int*)malloc(sizeof(int)*G->numVertexs);
if (!vertexSign)
exit(-1);
//存放当前树与其他部分的距离。
int *wightSign=(int*)malloc(sizeof(int)*G->numVertexs);
if (!wightSign)
exit(-1);
int vertexNum;
//将V0作为第一个树的节点
for (int i=0;i<G->numVertexs;i++)
{
vertexSign[i]=0;
wightSign[i]=G->arc[0][i];
}
//从已经加入树的顶点开始,每次新加入一个与树的距离最近的顶点,直到所有顶点都加入到树中
for (int i=1;i<G->numVertexs;i++)
{
vertexNum=FindMiniWeight(G,wightSign);
printf("新加入树的边为:(%d,%d) %d\n",vertexSign[vertexNum],vertexNum,wightSign[vertexNum]);
AddTree(G,vertexSign,wightSign,vertexNum);
}
}
注:这是用邻接矩阵实现的,G中 numVertexs是图中顶点的数目,arc是一个二维数组,用 INFINITY表示一个极大的数,模拟∞,可以是10000,arc[i][j]的值表示顶点i和j的边的权值当为 INFINITY表示没有边。参考《大话数据结构》