• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 详解图的应用(最小生成树、拓扑排序、关键路径、最短路径)

详解图的应用(最小生成树、拓扑排序、关键路径、最短路径)

作者:hguisu 字体:[增加 减小] 来源:互联网 时间:2017-05-28

hguisu 通过本文主要向大家介绍了最小生成树和最短路径,最小生成树,最小生成树算法,最小生成树prim算法,prim算法求最小生成树等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

1.最小生成树:无向连通图的所有生成树中有一棵边的权值总和最小的生成树

1.1 问题背景:
假设要在n个城市之间建立通信联络网,则连通n个城市只需要n—1条线路。这时,自然会考虑这样一个问题,如何在最节省经费的前提下建立这个通信网。在每两个城市之间都可以设置一条线路,相应地都要付出一定的经济代价。n个城市之间,最多可能设置n(n-1)/2条线路,那么,如何在这些可能的线路中选择n-1条,以使总的耗费最少呢?

1.2 分析问题(建立模型):

可以用连通网来表示n个城市以及n个城市间可能设置的通信线路,其中网的顶点表示城市,边表示两城市之间的线路,赋于边的权值表示相应的代价。对于n个顶点的连通网可以建立许多不同的生成树,每一棵生成树都可以是一个通信网。即无向连通图的生成树不是唯一的。连通图的一次遍历所经过的边的集合及图中所有顶点的集合就构成了该图的一棵生成树,对连通图的不同遍历,就可能得到不同的生成树。

图 G5无向连通图的生成树 为(a)、(b)和(c)图所示:

G5

G5的三棵生成树:

可以证明,对于有n 个顶点的无向连通图,无论其生成树的形态如何,所有生成树中都有且仅有n-1 条边。

1.3最小生成树的定义:

如果无向连通图是一个网,那么,它的所有生成树中必有一棵边的权值总和最小的生成树,我们称这棵生成树为最小生成树,简称为最小生成树。

最小生成树的性质:
假设N=(V,{ E}) 是个连通网,U是顶点集合V的一个非空子集,若(u,v)是个一条具有最小权值(代价)的边,其中,

则必存在一棵包含边(u,v)的最小生成树。

1.4 解决方案:

两种常用的构造最小生成树的算法:普里姆(Prim)和克鲁斯卡尔(Kruskal)。他们都利用了最小生成树的性质

1.普里姆(Prim)算法:有线到点,适合边稠密。时间复杂度O(N^2)

假设G=(V,E)为连通图,其中V 为网图中所有顶点的集合,E 为网图中所有带权边的集合。设置两个新的集合U 和T,其中

集合U(顶点集) 用于存放G 的最小生成树中的顶点,

集合T (边集合)存放G 的最小生成树中的边。

T ,U的初始状态:令集合U 的初值为U={u1}(假设构造最小生成树时,从顶点u1 出发),集合T 的初值为T={}。

Prim 算法的思想是:从所有u∈U,v∈V-U 的边中,选取具有最小权值的边(u,v)∈E,将顶点v 加入集合U 中,将边(u,v)加入集合T 中,如此不断重复,直到U=V 时,最小生成树构造完毕,这时集合T 中包含了最小生成树的所有边。

Prim 算法可用下述过程描述,其中用wuv 表示顶点u 与顶点v 边上的权值。
(1)U={u1},T={};
(2)while (U≠V)do
(u,v)=min{wuv;u∈U,v∈V-U }
T=T+{(u,v)}
U=U+{v}
(3)结束。
按照Prim 方法,从顶点1 出发,该网的最小生成树的产生过程如图:

为实现Prim 算法,需设置两个辅助closedge,用来保存U到集合V-U 的各个顶点中具有最小权值的边的权值。对每个Vi∈(V-U )在辅助数组中存在一个相应的分量closedge[i-1],它包括两个域:

typedef struct ArcNode

{

int adjvex; //adjex域存储该边依附的在U中的顶点
VrType lowcost; //lowcost域存储该边上的权重
}closedge[MAX_VERTEX_NUM];

显然:

初始状态时,U={v1}(u1 为出发的顶点),则到V-U 中各项中最小的边,即依附顶点v1的各条边中,找到一条代价最小的边(u0,v0)= (1,3)为生成树上一条边。
同时将v0(=v3)并入集合U中。然后修改辅助数组的值。

1)将closedge[2].lowcost = 0;//表示顶点V3三已经并入U

2) 由于边(v2,v3)的权值小于closedge[1].lowcost,故需修改closedge[1]为边(v2,v3)及其权值,同理修改closedge[4],closedge[5].

closedge[1].adjvex = 3.

closedge[1].lowcost = 5.

closedge[4].adjvex = 1.

closedge[4].lowcost = 5.

closedge[5].adjvex = 3.

closedge[5].lowcost = 6.

以此类推,直至U = V;

下图给出了在用上述算法构造网图7.16的最小生成树的过程中:


Prim 算法实现:

按照算法框架:

(1)U={u1},T={};
(2)while (U≠V)do
(u,v)=min{wuv;u∈U,v∈V-U }
T=T+{(u,v)}
U=U+{v}
(3)结束。
当无向网采用二维数组存储的邻接矩阵存储时,Prim 算法的C 语言实现为:

//记录从顶点集U到V—U的代价最小的边的辅助数组定义: 
 // struct{ 
 // VertexType adjvex; 
 // VRType lowcost; 
 // }closedge[ MAX_VERTEX_NUM ] 
void MiniSpanTree_PRIM (MGraph G,VertexType u){ 
//用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边。 
 k =LocateVex(G,u); 
 for(j=0; j<G.vexnum; ++j) 
  if(j!=k) closedge[j] ={u ,G.arcs[k][j].adj}; // {adjvex , lowcost} 
 closedge[k].lowcost =0; //初始,U={u} 
 for( i=1;i<G.vexnum;++i){ //选择其余G.vexnum-1个顶点 
  k=minimum(closedge); 
  printf(closedge[k].adjvex, G.vexs[k]);//输出生成树的边 
  //第k顶点并入U集 
  closedge[k].lowcost=0; 
  for(j=0; j<G.vexnum; ++j) 
   if (G.acrs[k][j].adj<closedge[j].lowcost) closedge[j]={G.vexs[k],G.arcs[k][j].adj}; 
 }//for 
}//MiniSpanTree 

</div>

假设网中有n个顶点,则第一个进行初始化的循环语句的频度为n,第二个循环语句的频度为n-1。其中有两个内循环:其一是在closedge[v].lowcost中求最小值,其频度为n-1;其二是重新选择具有最小代价的边,其频度为n。 由此,普里姆算法的时间复杂度为O(n2),与网中的边数无关,因此适用于求边稠密的网的最小生成树。
2.克鲁斯卡尔(Kruskal) :由点到线,适合边稀疏的网。时间复杂度:O(e * loge)

Kruskal 算法是一种按照网中边的权值递增的顺序构造最小生成树的方法。

基本思想是:

1) 设无向连通网为G=(V,E),令G 的最小生成树为T,其初态为T=(V,{}),即开始时,最小生成树T 由图G 中的n 个顶点构成,顶点之间没有一条边,这样T 中各顶点各自构成一个连通分量。

2) 在E中选择代价最小的边,若该边依附的顶点落在T中不同的连通分量,则将此边加入到T中,否则舍弃此边而选择下一条边(若该边依附的两个顶点属于同一个连通分量,则舍去此边,以免造成回路)。依此类推,当T 中的连通分量个数为1 时,此连通分量便为G 的一棵最小生成树。

按照Kruskal 方法构造最小生成树的过程如图所示:

在构造过程中,按照网中边的权值由小到大的顺序,不断选取当前未被选取的边集中权值最小的边。依据生成树的概念,n 个结点的生成树,有n-1 条边,故反复上述过程,直到选取了n-1 条边为止,就构成了一棵最小生成树。


Kruskal 算法的实现:
算法的框架:

构造非连通图T=(V,{})

k = i= 0;//k为边数

while(k《< n-1) {

i++;

检查边E中第i条边的权值

最小边(u,v)

若(u,v) 加入T不是T产生回路,

则(u,v)加入T,且k++

}

c语言实现:

C 语言实现Kruskal 算法,其中函数Find 的作用是寻找图中顶点所在树的根结点在数组father 中的

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 详解图的应用(最小生成树、拓扑排序、关键路径、最短路径)

相关文章

  • 2017-08-17C和C++的内存操作小贴士(一):const char*的内存释放问题
  • 2017-05-28详解C语言的exp()函数和ldexp()函数以及frexp()函数
  • 2017-05-28简单掌握C++编程中的while与do-while循环语句使用
  • 2017-05-28C 二分查找 递归与非递归的实现代码
  • 2017-05-28C++ MD5的源码实例详解
  • 2017-05-28浅谈C语言中strcpy,strcmp,strlen,strcat函数原型
  • 2017-05-28C++ 中dynamic_cast&lt;&gt;的使用方法小结
  • 2017-05-28c++类构造函数详解
  • 2017-05-28C语言中计算正弦的相关函数总结
  • 2017-05-28实例讲解C++编程中的虚函数与虚基类

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 基于字符串移位包含的问题详解
    • C++中判断成员函数是否重写
    • c++函数中的指针参数与地址参数区别介绍
    • C语言中socket相关网络编程函数小结
    • C++语言数据结构 串的基本操作实例代码
    • C++普通函数指针与成员函数指针实例解析
    • C/C++仿华容道小游戏
    • VC多线程编程详解
    • 华为面试题答案找出最大长度子字符串
    • C++输入输出操作符重载的深入分析

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有