算法核心思想:
新 加 入 点 后 , 每 次 添 加 权 值 最 小 的 边 \color{red}{新加入点后,每次添加权值最小的边} 新加入点后,每次添加权值最小的边
变量及数据结构解释:(完整代码在最后)
int W[8][8]=
{{0,1,2,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX},
{1,0,INT_MAX,4,5,INT_MAX,INT_MAX,3},
{2,INT_MAX,0,3,INT_MAX,4,INT_MAX,INT_MAX},
{INT_MAX,4,3,0,3,4,INT_MAX,INT_MAX},
{INT_MAX,5,INT_MAX,3,0,2,3,INT_MAX},
{INT_MAX,INT_MAX,6,7,2,0,8,9},
{INT_MAX,INT_MAX,INT_MAX,INT_MAX,3,INT_MAX,0,INT_MAX},
{INT_MAX,3,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,0}};
上面是无向图的邻接链表
参数表n——点的个数
ans 二维数组——保存最小生成树的邻接链表
temp 数组——当前可选边(在这里找最小权值)
结构体Node——value为权值,father为由哪个点发出的
struct Node {
int value;
int father;
};
(“由哪个点发出”是为了帮助算法理解我才这样解释,图仍然是无向图)
(Prime算法在确认一条边后,会衍生出新的可选边)
代码具体解析:
while循环—— 一次确认一个点
for(i=0;i<n;i++){
if(temp[i].value==-1)continue; //已经贪心确定了的就不必再比了
if(temp[i].value>W[mark][i]){
temp[i].value=W[mark][i];
temp[i].father=mark;
}
if(temp[i].value<temp[Min].value)Min=i; //反正就是优胜劣汰
}
上面的循环为 确 认 新 点 后 可 选 边 的 更 新 和 找 到 权 值 最 小 的 边 \color{red}{确认新点后可选边的更新和找到权值最小的边} 确认新点后可选边的更新和找到权值最小的边
这是整个算法的核心,也是难点
我在 temp 数组的更新这做了一些 规 定 \color{red}{规定} 规定
1. 已 经 确 认 了 的 点 就 不 必 再 操 作 了 \color{red}{1.已经确认了的点就不必再操作了 } 1.已经确认了的点就不必再操作了
( 即 权 值 被 置 成 − 1 的 ) \color{green}{(即权值被置成-1的)} (即权值被置成−1的)
2. 有 新 的 权 值 更 小 的 就 把 原 先 的 值 给 更 新 掉 ( 尽 管 那 条 边 还 没 用 过 就 要 被 替 换 掉 ) \color{red}{2.有新的权值更小的就把原先的值给更新掉(尽管那条边还没用过就要被替换掉)} 2.有新的权值更小的就把原先的值给更新掉(尽管那条边还没用过就要被替换掉)
( 这 两 步 很 妙 , 把 所 需 空 间 压 缩 了 很 多 , 千 万 要 好 好 理 解 ! ) \color{green}{(这两步很妙,把所需空间压缩了很多,千万要好好理解!)} (这两步很妙,把所需空间压缩了很多,千万要好好理解!)
再剩下来的就是在ans数组中记录最小生成树了
同时,为下次确认新点做准备~
struct Node {
int value;
int father;
};
int** prime(char start,int n){
int i,j;
int mark=start-'A';
int**ans=new int*[n];
for(i=0;i<n;i++){
ans[i]=new int[n];
memset(ans[i],0,4*n);
}
Node*temp=new Node[n];
for(i=0;i<n;i++){
temp[i].value=INT_MAX;
temp[i].father=mark; //结构体保存来处
}
temp[mark].value=-1;
int count=0;
int Min=mark+1;
while(count<n-1){
for(i=0;i<n;i++){
if(temp[i].value==-1)continue; //已经贪心确定了的就不必再比了
if(temp[i].value>W[mark][i]){
temp[i].value=W[mark][i];
temp[i].father=mark;
}
if(temp[i].value<temp[Min].value)Min=i; //反正就是优胜劣汰
} //加入新点到集合后,贪心权值最小的就够了
ans[temp[Min].father][Min]=1;
temp[Min].value=-1;
mark=Min;
for(j=0;j<n;j++){
if(temp[j].value!=-1){ //Min一定得变!!而且还得是到未知点身上
Min=j;
break;
}
}
count++;
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cout<<ans[i][j];
}
cout<<endl;
}
free(temp);
return ans;
}