7.4.1 prim算法
用prim算法求图的最小生成树:
1) 由两个数组记录prim求最小生成树的过程中所需的信息
a) Lowcost[Max],记录最小生成树中每个【叶子结点】和【其他顶点】组成的所有边的权重,没有边的,权重就是
i. 长度就是顶点的个数
b) Adjvex[Max],记录Lowcost[Max]数组中,每条边所对应的一个顶点,也就是说,这个边是属于这个顶点的,Adjvex[Max]记录的就是这个顶点在图中的下标(可以比喻成是一个线性函数,Adjvex[Max]就是自变量的集合,Lowcost[Max]就是函数值的集合)
c) Adjvex[Max] 的 元素 与 元素对应的下标构成的边,是在最小生成书中的,对应下标的Adjvex[Max]的元素,就是这条边的权重
d) 有这么几个要解决的问题:
i. 选出Lowcost[Max]数组中的元素
1. Lowcost[0] = 0 ,Adjvex[0] = 0 -> 将V0添加到最小生成树中,也就是最小生成树的根
2. Lowcost数组的初始值就是【V0参与生成所有边的权重】的集合
ii. 根据Lowcost[Max]数组数据与 邻接矩阵中,第【最小生成树新添加顶点的下标】行的数据比较,确定Adjvex[Max]数组的元素,并且将较小的边,替换Lowcost[Max]中对应下标的边(相当于是设置自变量,和函数值)
iii. 选出Lowcost[Max]数组后,找出最小的权重的边,并添加到最小生成树,权重为0,就算是添加到最小生成树中,所以每次选出之后,都要将Lowcost[i] = 0,k =i (记录最小权重边的下标)(一旦成为最小生成树的一部分,权重(函数值)=0)
(Adjvex[k],k)就是当前的最小权重边
iv. 将邻接矩阵中的第k行的数据与 Lowcost数组中的比较
满足(lowcost[j] !=0 && arc[k][j] < lowcost[j])
è lowcost[j] = arc[k][j] Adjvex[j] = k
这其实就是将【新添加到最小生成树中的边】的【另一个顶点(比如V1)所参加生成的边中(权重信息存储在邻接矩阵的第1行),权重小于lowcost对应的值的边】添加到lowcost数组中
lowcost[j]!=0 表示已经在最小生成树中的边不参与比较
2) 代码解析:
void MiniSpanTree_Prim(MGraph G)
{
int min,i,j,k;
int adjvex[Max]; //存储lowcost[]存储的边的一个顶点,元素与对应下标组成边
int lowcost[Max]; //存储最小生成树所有叶子结点的所有边的权重
lowcost[0] = 0; //将V0放到最小生成树中,V0到V0是没有权值的
adjvex[0] = 0; // V0到V0是没有边的
//初始化两个数组
for(i = 1;i < G.numVertex; i++)
{
lowcost[i] = G.arc[0][i];
adjvex[i]= 0;
}
//循环图中的每一个顶点
for(i = 1; i < G.numVertex;i++)
{
min = 65535;
j = 1; //因为V0已经在最小生成树中,所以从下标为1的顶点开始
k = 0;
while(j < G.numVertex)
{
// lowcost[i] != 0 表示顶点没有在最小生成树中
// lowcost[i] <min 找出当前lowcost数组中最小的元素
if(lowcost[i] != 0&& lowcost[i] < min)
{
min =lowcost[i];
k = j;
}
j++;
}
cout << adjvex[k]<< k; //可以是其他的操作
lowcost[k] = 0; //将lowcost数组中最小元素置0(也就是附在顶点k上的某条边的权重置0,表示k顶点加入最小生成树中)
//更新lowcost数组元素,将现有的lowcost数组中的元素,依次与邻接矩阵第k行元素比较,较小的就替换lowcost数组中对应的元素
// lowcost[j] != 0表示已经在最小生成树中的顶点不用遍历
for(j = 1; j <G.numVertex; j++)
{
if(lowcost[j] != 0&& G.arc[k][j] < lowcost[j])
{
//依次与邻接矩阵第k行元素比较,较小的就替换lowcost数组中对应的元素
lowcost[j] =G.arc[k][j];
adjvex[j] =k; //将下标为k的顶点存入adjvex数组,k,j 组成一条边
}
}
}
}