图:最小生成树

生成树的代价:设G=(V,E)是一个无向连通网,生成树上各边的权值之和称为该生成树的代价
最小生成树:在图G所有生成树中,代价最小的生成树称为最小生成树
Prim算法
设G=(V, E)是具有n个顶点的连通网,
T=(U, TE)是G的最小生成树,
T的初始状态为U={u0}(u0∈V),TE={ },
重复执行下述操作:
在所有u∈U,v∈V-U的边中找一条代价最小的边(u, v)并入集合TE,同时v并入U,直至U=V。
prim算法需要不断读取任意两个顶点的信息,所以图用邻接矩阵存储
数组lowcost[n]:用来保存集合V-U中各顶点与集合U中顶点最短边的权值,lowcost[v]=0表示顶点v已加入最小生成树中;
数组adjvex[n]:用来保存该边所依附的(集合V-U中各顶点与集合U中顶点的最短边)集合U中的顶点。
lowcost[i]=w 表示顶点vi和顶点vk之间的权值为w,其中:vi∈ V-U 且vk ∈U
adjvex[i]=k.
prim算法:

  1. 初始化两个辅助数组lowcost(=arc[0][i])和adjvex(=0)(0是始点);
  2. 输出顶点u0,将顶点u0加入集合U中;
  3. 重复执行下列操作n-1次
    3.1 在lowcost中选取最短边(lowcost[k]),取对应的顶点序号k;
    3.2 输出顶点k和对应的权值;
    3.3 将顶点k加入集合U中(lowcost[k]=0);
    3.4 调整数组lowcost和adjvex;
Void prim(MGraph G){
    for(int i=1;i<G.vertexNu;i++){
        lowcost[i]=G.arc[0][i];  adjvex[i]=0;
    }
    lowcost[0]=0;
    for(i=1;i<G.vertexNum;i+++){
        k=MinEdge(lowcost,G.vertexNum)
        /*int min=MIN;
        for(int j=1; j<vertexNum; j++)
        {
            if(lowcost[j]!=0&&lowcost[j]<min)//lowcost[0]代表结点已加入U中
            {
                min=lowcost[j];
                k=j;
            }
        }*/
        cout<<K<<adjvex[k]<<lowcost[k];
        lowcost[k]=0;
         for(j=1;j<G.vertexNum;j++)
          if((G.arc[k][j]<lowcost[j]){
              lowcost[j]=G.arc[k][j];
              arcvex[j]=k;
           }
    }
}

时间复杂性O(n2);适用于求稠密网的最小生成树

Kruskal算法
因为Kruskal算法需要依此对图中的边进行操作,因此用边集数组来存储图。为了提高查找最短边的速度,可以先对边集数组上的权排序

  1. 初始化:U=V; TE={ };
  2. 循环直到T中的连通分量个数为1
    2.1 在E中寻找最短边(u,v);
    2.2 如果顶点u、v位于T的两个不同连通分量,则
    2.2.1 将边(u,v)并入TE;
    2.2.2 将这两个连通分量合并为一个;
    2.3 在E中标记边(u,v),使得(u,v)不参加后续最短边的选取;
    如何判断一条边所依附的两个顶点在同一个连通分两中(并查集)
    定义Parent[i]数组。数组分量的值表示顶点i的双亲节点(初值为-1;
    当一条边(u,v)的两个顶点的根结不同时,这两个结点属于不同的连通分量(利用parent 数组查找一棵树的根节点。当一个结点n的parent==-1,树的根节点即为n)
    如何将一条边所依附的两个顶点合并到同一个连通分量中
    要进行联通分量的合并 ,其中一个顶点所在的树的根节点为vex1,另一个顶点所在的树的根节点为vex2,则:parent[vex2]=vex1;求某棵树v所在的生成树的根节点,只需要延数组v=parent[v]不断查找v的双亲,直到parent[v]=-1.
struct EdgeType//边集数组
{
int from;//边所依附的两个顶点下标
int to;
int weight;//权值
}
int Find(int *parent, int node)
{
int f;
f=node;
while(parent[f]>-1)
 f=parent[f];
return f;
}
/*sort(edge,edge+n,cmp);//排序
   int num=0;
   int vex1,vex2;
   int parent[vertexNum];*/
   for(int i=0; i<vertexNum; i++)
   {
       parent[i]=-1;
   }
   int i;
   for(num=0,i=0; num<vertexNum-1; i++)
   {
       vex1=Find(parent,edge[i].from);
       vex2=Find(parent,edge[i].to);
       if(vex1!=vex2)
       {
           cout<<edge[i].from+1<<" "<<edge[i].to+1<<" ";
           parent[vex2]=vex1;
           num++;
       }
   }

因此时间复杂性为O(elog2e).
适用于求稀疏网的最小生成树。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值