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算法)的更多相关文章

  1. 图的最小生成树(Prim、Kruskal)

    理论: Prim: 基本思想:假设G=(V,E)是连通的,TE是G上最小生成树中边的集合.算法从U={u0}(u0∈V).TE={}开始.重复执行下列操作: 在所有u∈U,v∈V-U的边(u,v)∈E ...

  2. 无向带权图的最小生成树算法——Prim及Kruskal算法思路

    边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...

  3. 图的最小生成树的理解和实现:Prim和Kruskal算法

    最小生成树 一个连通图的生成树是一个极小的连通子图,它含有图中所有的顶点,但只有足以构成一棵树的n-1条边.我们将构造连通网的最小代价生成树称为最小生成树(Minimum Cost Spanning ...

  4. 图->连通性->最小生成树(普里姆算法)

    文字描述 用连通网来表示n个城市及n个城市间可能设置的通信线路,其中网的顶点表示城市,边表示两城市之间的线路,赋于边的权值表示相应的代价.对于n个定点的连通网可以建立许多不同的生成树,每一棵生成树都可 ...

  5. [数据结构]最小生成树算法Prim和Kruskal算法

    最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树.  例如,对于如上图G4所示的连通网可以有多棵权值总 ...

  6. C++编程练习(11)----“图的最短路径问题“(Dijkstra算法、Floyd算法)

    1.Dijkstra算法 求一个顶点到其它所有顶点的最短路径,是一种按路径长度递增的次序产生最短路径的算法. 算法思想: 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的 ...

  7. 最小生成树(Prim算法+Kruskal算法)

    什么是最小生成树(MST)? 给定一个带权的无向连通图,选取一棵生成树(原图的极小连通子图),使生成树上所有边上权的总和为最小,称为该图的最小生成树. 求解最小生成树的算法一般有这两种:Prim算法和 ...

  8. hdu 1233 还是畅通工程 最小生成树(prim算法 + kruskal算法)

    还是畅通工程                                                                            Time Limit: 4000/2 ...

  9. 最小生成树 Prim算法 Kruskal算法实现

    最小生成树定义 最小生成树是一副连通加权无向图中一棵权值最小的生成树. 在一给定的无向图 G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即,而 w(u, v) 代表此边的 ...

随机推荐

  1. mysql 查找重复的数据

    Select Name,Count(*) From A Group By Name Having Count(*) > 1   Name是字段

  2. 《数据结构与算法分析:C语言描述》读书笔记------List的C语言实现

    List的简单实现.在GCC下测试通过. list.h #ifndef _List_H /*List数据结构的简单实现*/ struct Node; typedef struct Node Node; ...

  3. 内层div的margin-top影响外层div——引出外边距合并Collapsing margins

    内层div的margin-top影响外层div——引出外边距合并Collapsing margins 作者:zccst 今天才算是了解边距合并.正如一位前辈所言,每一个CSS的坑,都让你学到不少知识. ...

  4. lpc1768的系统时钟

    #define XTAL_FREQ   12000000 #define VECT_TAB_OFFSET  0x0000 void SystemInit(void) { //PLL0时钟配置 LPC_ ...

  5. js/jQuery实现类似百度搜索功能

    一.页面代码:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www. ...

  6. 虚拟机联网及远程连接-Linux基础环境命令学习笔记

    1.ifconfig命令=ip a命令,查看IP地址 网卡默认名称eth0. Bcast 广播地址2.xshell or secureCRT远程连接 ssh root@地址 xmanager 远程桌面 ...

  7. ubuntu14.04安装配置jdk1.8.0_25

    Reference: http://jingyan.baidu.com/article/eb9f7b6d8f82a6869364e8a7.html 今天尝试在ubuntu14.04 LTS上安装jdk ...

  8. Python collections.defaultdict() 与 dict的使用和区别

    看样子这个文档是难以看懂了.直接看示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import collections s = [('yellow', ...

  9. 1833: [ZJOI2010]count 数字计数

    1833: [ZJOI2010]count 数字计数 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 2951  Solved: 1307[Submit][ ...

  10. python中使用urllib2伪造HTTP报头的2个方法

    在采集网页信息的时候,经常需要伪造报头来实现采集脚本的有效执行 下面,我们将使用urllib2的header部分伪造报头来实现采集信息 方法1. ? 1 2 3 4 5 6 7 8 9 10 11 1 ...