最小生成树Prime算法

算法核心思想:

新 加 入 点 后 , 每 次 添 加 权 值 最 小 的 边 \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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值