C++编程练习(10)----“图的最小生成树“(Prim算法、Kruskal算法)
1、Prim 算法
以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树。
2、Kruskal 算法
直接寻找最小权值的边来构建最小生成树。
比较:
Kruskal 算法主要是针对边来展开,边数少时效率会非常高,所以对于稀疏图有很大的优势。
Prim 算法针对顶点展开,对于稠密图,即边数非常多的情况下会更好。
具体代码如下:
/* Graph.h头文件 */
/*包含图的建立:图的深度优先遍历、图的广度优先遍历*/
/*包含图的最小生成树:Prim 算法、Kruskal 算法*/
#include<iostream>
#include"LinkQueue.h"
#define MAXVEX 100
#define MAXEDGE 100
#define INFINITY 65535
#define TRUE 1
#define FALSE 0
typedef char VertexType;
typedef int EdgeType;
typedef int Boolean;
using namespace std; /*邻接矩阵方式建立图*/
class MGraph{
public:
VertexType vexs[MAXVEX];
EdgeType arc[MAXVEX][MAXVEX];
int numVertexes,numEdges;
}; /*建立无向网图的邻接矩阵表示*/
void CreateMGraph(MGraph *G)
{
int i,j,k,w;
cout<<"输入顶点数和边数:"<<endl;
cin>>G->numVertexes>>G->numEdges;
cin.clear();
cout<<"输入顶点信息:"<<endl;
for(i=0;i<G->numVertexes;i++)
{
cin>>G->vexs[i];
cin.clear();
}
for(i=0;i<G->numVertexes;i++)
for(j=0;j<G->numVertexes;j++)
{
if (i==j)
G->arc[i][j]=0;
else
G->arc[i][j]=INFINITY;
}
for(k=0;k<G->numEdges;k++)
{
cout<<"输入边(vi,vj)上的下标i,下标j和权w:"<<endl;
cin>>i>>j>>w;
cin.clear();
G->arc[i][j]=w;
G->arc[j][i]=G->arc[i][j];
}
} /*邻接矩阵的深度优先递归算法*/
Boolean visited[MAXVEX]; /*访问标志的数组*/
void DFS(MGraph G,int i)
{
int j;
visited[i]=TRUE;
cout<<G.vexs[i]; /*打印顶点,也可以其他操作*/
for(j=0;j<G.numVertexes;j++)
if(G.arc[i][j]==1 && !visited[j])
DFS(G,j); /*对为访问的邻接顶点递归调用*/
}
/*邻接矩阵的深度优先遍历操作*/
void DFSTraverse(MGraph G)
{
cout<<"\n深度优先遍历结果为:"<<endl;
int i;
for(i=0;i<G.numVertexes;i++)
visited[i]=FALSE; /*初始化所有顶点状态都是未访问过状态*/
for(i=0;i<G.numVertexes;i++)
if(!visited[i]) /*对未访问过的顶点调用DFS,若是连通图,只会执行一次*/
DFS(G,i);
cout<<endl;
} /*邻接矩阵的广度遍历算法*/
void BFSTraverse(MGraph G)
{
cout<<"广度优先遍历结果为:"<<endl;
int i,j;
LinkQueue Q;
for(i=0;i<G.numVertexes;i++)
visited[i]=FALSE;
for(i=0;i<G.numVertexes;i++)
{
if(!visited[i])
{
visited[i]=TRUE;
cout<<G.vexs[i];
Q.EnQueue(i);
while(!Q.QueueEmpty())
{
Q.DeQueue(&i);
for(j=0;j<G.numVertexes;j++)
{
if(G.arc[i][j]==1 && !visited[j])
{
visited[j]=TRUE;
cout<<G.vexs[j];
Q.EnQueue(j);
}
}
}
}
}
cout<<endl;
} /* Prim算法生成最小生成树 */
void MiniSpanTree_Prim(MGraph G)
{
cout<<"Prim算法生成最小生成树,结果为:"<<endl;
int min,i,j,k;
int adjvex[MAXVEX];
int lowcost[MAXVEX];
lowcost[0]=0;
adjvex[0]=0;
for(i=1;i<G.numVertexes;i++)
{
lowcost[i]=G.arc[0][i];
adjvex[i]=0;
}
for(i=1;i<G.numVertexes;i++)
{
min=INFINITY;
j=1;k=0;
while(j<G.numVertexes)
{
if(lowcost[j]!=0 && lowcost[j]<min)
{
min=lowcost[j];
k=j;
}
j++;
}
cout<<"("<<adjvex[k]<<","<<k<<")"<<endl;
lowcost[k]=0;
for(j=1;j<G.numVertexes;j++)
{
if(lowcost[j]!=0 && G.arc[k][j]<lowcost[j])
{
lowcost[j]=G.arc[k][j];
adjvex[j]=k;
}
}
}
cout<<endl;
} /* Kruskal 算法生成最小生成树 */ class Edge{ /*对边集数组Edge结构的定义*/
public:
int begin;
int end;
int weight;
}; void Swap(Edge *edges,int i,int j) /* 交换权值 以及头和尾 */
{
int temp;
temp=edges[i].begin;
edges[i].begin=edges[j].begin;
edges[j].begin=temp;
temp=edges[i].end;
edges[i].end=edges[j].end;
edges[j].end=temp;
temp=edges[i].weight;
edges[i].weight=edges[j].weight;
edges[j].weight=temp;
} void sort(Edge edges[],MGraph *G) /* 对权值进行排序 */
{
int i,j;
for ( i=0;i<G->numEdges;i++)
{
for ( j=i+1;j<G->numEdges;j++)
{
if (edges[i].weight>edges[j].weight)
{
Swap(edges,i,j);
}
}
}
cout<<"权排序之后的为:"<<endl;
for (i=0;i<G->numEdges;i++)
{
cout<<"("<<edges[i].begin<<","<<edges[i].end<<")"<<endl;
}
} int Find(int *parent,int f) /*查找连线顶点的尾部下标*/
{
while (parent[f]>0)
f=parent[f];
return f;
} void MiniSpanTree_Kruskal(MGraph G)
{
int i,j,n,m;
Edge edges[MAXEDGE];
int parent[MAXVEX]; /*将邻接数组G转化为边集数组edges并按权由小到大排序*******BEGIN*********/
int k=0;
for ( i=0;i<G.numVertexes-1;i++)
{
for (j=i+1;j<G.numVertexes;j++)
{
if (G.arc[i][j]<INFINITY)
{
edges[k].begin=i;
edges[k].end =j;
edges[k].weight=G.arc[i][j];
k++;
}
}
}
sort(edges, &G);
/***************END***********************/ for (i=0;i<G.numVertexes;i++)
parent[i]=0; /* 初始化数组值为0 */
cout<<"Kruskal 算法生成最小生成树,结果为:"<<endl;
for (i=0;i<G.numEdges;i++) /* 循环每一条边 */
{
n=Find(parent,edges[i].begin);
m=Find(parent,edges[i].end);
if (n!=m) /* 假如n与m不等,说明此边没有与现有的生成树形成环路 */
{
parent[n]=m; /* 将此边的结尾顶点放入下标为起点的parent中。 */
/* 表示此顶点已经在生成树集合中 */
cout<<"("<<edges[i].begin<<","<<edges[i].end<<") "<<edges[i].weight<<endl;
}
}
}
对于如下所示的图:
运行程序,结果如下:
C++编程练习(10)----“图的最小生成树“(Prim算法、Kruskal算法)的更多相关文章
- 图的最小生成树(Prim、Kruskal)
理论: Prim: 基本思想:假设G=(V,E)是连通的,TE是G上最小生成树中边的集合.算法从U={u0}(u0∈V).TE={}开始.重复执行下列操作: 在所有u∈U,v∈V-U的边(u,v)∈E ...
- 无向带权图的最小生成树算法——Prim及Kruskal算法思路
边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...
- 图的最小生成树的理解和实现:Prim和Kruskal算法
最小生成树 一个连通图的生成树是一个极小的连通子图,它含有图中所有的顶点,但只有足以构成一棵树的n-1条边.我们将构造连通网的最小代价生成树称为最小生成树(Minimum Cost Spanning ...
- 图->连通性->最小生成树(普里姆算法)
文字描述 用连通网来表示n个城市及n个城市间可能设置的通信线路,其中网的顶点表示城市,边表示两城市之间的线路,赋于边的权值表示相应的代价.对于n个定点的连通网可以建立许多不同的生成树,每一棵生成树都可 ...
- [数据结构]最小生成树算法Prim和Kruskal算法
最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树. 例如,对于如上图G4所示的连通网可以有多棵权值总 ...
- C++编程练习(11)----“图的最短路径问题“(Dijkstra算法、Floyd算法)
1.Dijkstra算法 求一个顶点到其它所有顶点的最短路径,是一种按路径长度递增的次序产生最短路径的算法. 算法思想: 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的 ...
- 最小生成树(Prim算法+Kruskal算法)
什么是最小生成树(MST)? 给定一个带权的无向连通图,选取一棵生成树(原图的极小连通子图),使生成树上所有边上权的总和为最小,称为该图的最小生成树. 求解最小生成树的算法一般有这两种:Prim算法和 ...
- hdu 1233 还是畅通工程 最小生成树(prim算法 + kruskal算法)
还是畅通工程 Time Limit: 4000/2 ...
- 最小生成树 Prim算法 Kruskal算法实现
最小生成树定义 最小生成树是一副连通加权无向图中一棵权值最小的生成树. 在一给定的无向图 G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即,而 w(u, v) 代表此边的 ...
随机推荐
- scp命令和sftp命令
scp帮助命令: man scpscp功能:下载远程文件或者目录到本地,如果想上传或者想下载目录,最好的办法是采用tar压缩一下,是最明智的选择.从远程主机下载东西到本地电脑拷贝文件命令 scp us ...
- Linux环境变量相关文件
执行顺序为: /etc/profile -> (~/.bash_profile | ~/.bash_login | ~/.profile) -> ~/.bashrc -> /etc/ ...
- php连接mysql数据库(新浪云SAE)
新浪云提供了免费的创建服务器端应用的服务.网址为:https://www.sinacloud.com/ 在上面创建好应用,然后在本地使用记事本编写应用的代码如下: <?php echo &quo ...
- 总结分享十大iOS开发者最喜爱的库 分类: ios相关 app相关 2015-04-03 16:43 320人阅读 评论(0) 收藏
该10大iOS开发者最喜爱的库由"iOS辅导团队"成员Marcelo Fabri组织投票选举而得,参与者包括开发者团队,iOS辅导团队以及行业嘉宾.每个团队都要根据以下规则选出五个 ...
- 理解Action,Service和Dao功能(转)
真正理解.区分Action,Service和Dao功能 在不分层的系统里,我们可以将所有的代码都写到一个地方,比如struts的Action类.在这里,我们不仅要处理页面逻辑,还要做业务逻辑,还要 ...
- eclipse安装maketplace插件
对于默认eclipse是没有marketplace插件的,但是marketplace确实是非常好用的,可以在上面下载各种插件. 1.Help-->Install new Software 2.输 ...
- 【推荐】PHP中格式化时间函数date与gmdate的区别 | 修改PHP的默认时区
PHP中的时间有2个格式化函数:date()和gmdate(),在官方的文档中的描述为: date -- 格式化一个本地时间/日期 gmdate -- 格式化一个 GMT/UTC 日期/时间,返回的是 ...
- MySQL数据库面试
1. MySql的存储引擎的不同 特点 Myisam BDB Memory InnoDB Archive 存储限制 没有 没有 有 64TB 没有 事务安全 支持 支持 锁机制 表锁 页锁 ...
- 微信上传图片接口实现 JS
//2.微信上传图片接口实现 <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></scri ...
- Reactive 网络状态 Activity indicator view
转动属性:Animating RAC(self.searchActivity, hidden) = [self.m_viewModel.m_searchCommand.executing not];