最小生成树的应用

最小生成树的应用
最小生成树的应用

武 夷 学 院

课程设计报告

课程名称: 数据结构(C 言语版本) 设计题目: 最小生成树的应用 学生班级: 10计科1班

学生姓名: 陈娟,谢贤根,黄伟伟,陈开槟 指导教师: 林丽惠 完成日期:

2012-01-05

课程设计项目研究报告

目录

一、问题描述及基本要求....................................................................................... - 1 -

二、实现本程序需要解决的问题如下................................................................. - 1 -

三、测试数据......................................................................................................... - 2 -

四、算法思想......................................................................................................... - 3 -

五、模块划分............................................................................ 错误!未定义书签。

六、算法设计与分析............................................................................................. - 7 -

七、源程序........................................................................................................... - 11 -

八、测试数据....................................................................................................... - 14 -

九、课程设计项目进度表及任务分配表及任务分配表................................... - 15 -

十、设计心得....................................................................................................... - 16 -十一参考文献....................................................................................................... - 17 -

一、为题描述及基本要求

在n个城市间建立通信网络,需架设n-1条线路。求解如何以最低经济代价建设此通信网,这是一个最小生成树问题。要求:(1)利用普利姆算法求网的最小生成树;(2)输出生成树中各边及权值。

二、实现本程序需要解决的问题如下

(1)、如何选择存储结构去建立一个带权网络。

(2)、如何在所选存储结构下输出这个带权网络。

(3)、如何实现prim算法的功能。

(4)、如何从每个顶点开始找到所有的最小生成树的顶点。

(5)、如何输出最小生成树的边及其权值。

此问题的关键在于如何实现prim算法,实现的过程中如何得到构成最小生成树的所有顶点,此外输出也是一个关键问题所在,在此过程中经过了多次调试。首先我们对问题进行大致的概要分析:

这个问题主要牵涉到通过prim的基本算法思想实现程序所要求的功能,该算法的主要思想是:假设N=(V,{E})是连通网,TE是N上最小生成树中边的集合。算法从U={u0}( u0∈V),TE={}开始,重复执行下述操作:在所有u∈U,v∈V-U的边(u,v)∈E中找一条代价最小的边(u0,v0)并入集合TE,同时v0并入U,直至U=V为止。此时TE中必有n-1条边,则T=(V,{E})为N的最小生成树。

问题的输入数据的格式为:首先提示输入带权网络的顶点边数,我定义的为整形数据型,然后输入每一条边的信息,即边的两个顶点以及权值,是十进制整数类型,这样我们就建立一个带权网络,并用邻接矩阵来存储,生成一个方阵显示出来。

问题的输出数据格式为:输出是以邻接矩阵形式输出,以及从不同顶点开始生成的最小生成树。

题目要求以及达到目标:题目要求用prim算法实现给定无向网中边e和顶点n 实现生成的最小生成树,输出生成树中的各边及权值。

三、测试数据

第一组

顶点数(vertices)、边数(edge):4、5

起始节点(starting)、下个节点(terminal)、权值(weights):1,2,1

1,3,2

2,4,5

3,4,4

1,4,6 预测结果<1,2>1、<1,3>2、<3,4>4

第二组

顶点数(vertices)、边数(edge):6,10,

起始节点(starting)、下个节点(terminal)、权值(weights):1,2,6

1,3,1

1,4,5

2,3,5

2,5,3

3,5,6

3,4,5

3,6,4

4,6,2

5,6,6 预测结果<1,3>1、<3,6>4、<6,4>2、<3,2>5、<2,5>3

四、算法思想

普里姆算法的基本思想:普里姆算法是另一种构造最小生成树的算法,它是按逐个将顶点连通的方式来构造最小生成树的。

从连通网络N = { V, E }中的某一顶点u0 出发,选择与它关联的具有最小权值的边(u0, v),将其顶点加入到生成树的顶点集合U中。以后每一步从一个顶点在U中,而另一个顶点不在U中的各条边中选择权值最小的边(u, v),把该边加入到生成树的边集TE中,把它的顶点加入到集合U中。如此重复执行,直到网络中的所有顶点都加入到生成树顶点集合U中为止。

假设N=(V,{E})是一个连通网,TE是N上最小生成树中边的集合。则构造N的最小生成树的步骤如下:

(1)初始状态,TE为{},U={u0},u0∈V;

(2)在所有u∈U,v∈V-U的边(u,v) ∈E中找一条代价最小的边(u′,v′)并入TE,同时将v′并入U;

重复执行步骤(2)n-1次,直到U=V为止。

在普里姆算法中,为了便于在集合U和(V-U)之间选取权值最小的边,需要设置两个辅助数组closest和lowcost,分别用于存放顶点的序号和边的权值。

对于每一个顶点v∈V-U,closest[v]为U中距离v最近的一个邻接点,即边(v,closest[v]) 是在所有与顶点v相邻、且其另一顶点j∈U的边中具有最小权值的边,其最小权值为lowcost[v],即lowcost[v]=cost[v][closest[v]],采用邻接表作为存储结构:

设置一个辅助数组:

lowcost域存放生成树顶点集合内顶点到生成树外各顶点的各边上的当前最小权值;

closest域记录生成树顶点集合外各顶点距离集合内哪个顶点最近(即权值最小)。

用prim算法构造最小生成树的过程:

五、模块划分

(1)预处理

#include

#include

#define inf 9999

#define max 40

#define linelenght 77

(2)建立无向图

int adjg(int g[][max]) /* 建立无向图*/

{

int n,e,i,j,k,v1=0,v2=0,weight=0;

printf("Input the number of vertices, number of the edge:");

scanf("%d,%d",&n,&e);

while(e<=0||e>0.5*n*(n-1)||n>=max) /*最大边数为C n2,即0.5*n*(n-1)*/

{

error();

printf("Input the number of vertices, number of the edge:");

scanf("%d,%d",&n,&e);

}

for(i=1;i<=n;i++)

for(j=1;j<=n;j++)

g[i][j]=inf; /* 初始化矩阵,全部元素设为无穷大*/

for(k=1;k<=e;k++)

{

printf("Input the %d on the edge of the starting point, terminal, weights:",k);

scanf("%d,%d,%d",&v1,&v2,&weight);

while(v1==v2||v1>n||v2>n||v1<1||v2<1)

{

error();

printf("Input the %d on the edge of the starting point, terminal, weights:",k);

scanf("%d,%d,%d",&v1,&v2,&weight);

}

g[v1][v2]=weight; /* 无向网的邻接矩阵是对称矩阵*/

g[v2][v1]=weight;

}

return(n);

} /* 返回顶点个数n */

(3)输出无向图的邻接矩阵

void pri(int g[][max],int n) /* 输出无向图的邻接矩阵*/

{

int i,j;

for(i=0;i<=n;i++)

printf("%d\t",i);

for(i=1;i<=n;i++)

{

printf("\n%d\t",i);

for(j=1;j<=n;j++) /* 输出边的权值*/

{

if(g[i][j]==inf) printf("%c\t",'\354');

else printf("%d\t",g[i][j]);

}

}

printf("\n");

}

void prim(int g[][max],int n) /* prim函数*/

{

int lowcost[max],closest[max];

int i,j,k,min;

for(i=2;i<=n;i++)

{ lowcost[i]=g[1][i]; /* 初始化*/

closest[i]=1;

}

lowcost[1]=0; /* 标志顶点1加入U集合*/ for(i=2;i<=n;i++) /* 形成n-1条边的生成树*/ {

min=inf;

k=0;

for(j=2;j<=n;j++) /* 寻找权值最小的一条边,并把权值赋给min */

if((lowcost[j]

{

min=lowcost[j];

k=j;

}

printf("(%d,%d)%d\t",closest[k],k,min);

lowcost[k]=0; /* 顶点k加入U */

for(j=2;j<=n;j++) /* 修改由顶点k到其他顶点边的权值*/

if(g[k][j]

{

lowcost[j]=g[k][j];

closest[j]=k;

}

printf("\n");

}

}

(4)输出一条分割线

int priline(int h) /* 输出一条分割线*/

{

int g;

printf("\n|");

for(g=0;g

printf("*");

printf("|\n");

}

(5)提示错误信息

int error() /* 提示错误信息*/

{

printf("\n\n|************************E*R*R*O*R************************|\ n");

printf("Input errors or Data overflow!!! please re-enter\n\n");

fflush(stdin); /* 清除缓存*/

}

(6)主函数

void main() /* 主函数*/

{

int g[max][max],n;priline(linelenght);

n=adjg(g);priline(linelenght);priline(linelenght);

printf("Input the adjacency matrix without directed graph:\n");

pri(g,n);

printf("\n");

printf("Minimum spanning tree structure:\n");

prim(g,n);

getch();

}

六、算法设计与分析

(1)关于带权网络的存储形式

要实现对于任意给定带权网络和顶点,运用PRIM基本算法思想求解所有的最小生成树的运算。在这里我们首先要明确所选用的数据结构,即选用何种数据结构存储来存储带权网络,这是必选首先解决的问题,所以我们选择了图的邻接矩阵存储方式来存储带权网络,建图时采用邻接矩阵的结构,定义邻接矩阵用到了一维数组和二维数组,分别存储顶点信息和边的权值。由于该算法对图中的边的权值频繁比较,所以采用邻接矩阵比较方便,并在此基础上实现带权网络的建立以及输出显示。

(2)关于普利姆算法的基本思想

Prim算法求最小生成树的主要思想

此算法是普利姆与1957年提出的一种构造最小生成树的算法,主要思想是:假设N=(V,{E})是连通网,TE是N上最小生成树中边的集合。算法从U={u0}( u0∈V),TE={}开始,重复执行下述操作:在所有u∈U,v∈V-U的边(u,v)∈E中找一条代价最小的边(u0,v0)并入集合TE,同时v0并入U,直至U=V为止。此时TE中必有n-1条边,则T=(V,{E})为N的最小生成树。

对于最小生成树问题

最小生成树是指在所有生成树中,边上权值之和最小的生成树,另外最小生成树也可能是多个,他们之间的权值之和相等。

(3)概要设计

通过邻接矩阵的建立,可以将任意两点的权值存入其中,便于进行各边的权值的比较修改,在普利姆算法中,为实现这个算法需附设一个辅助数组closedge,以记录从U到V-U具有最小代价的边,对每个顶点vi∈V-U,在辅助数组中存在一个相应分量closedge[i-1],他包括两个域,其中lowcost存储该边上的权值。显然,

closedge[i-1].lowcost=Min{cost(u,vi)| u∈U}

从算法可以看出每加入一个顶点到U中,closedge数组都会发生相应的变化。程序模块之间的调用:在主函数中调用邻接矩阵的初始化函数,邻接矩阵的生成函数,PRIM算法的函数,图的构造函数,输出函数。邻接矩阵的生成函数主要解决的是边的信息存储问题,而PRIM算法的函数是解决计算出最小生成树的功能。

详细设计和编码

首先我在接下来给出总的流程:

结果分析:

本课程设计的要求

对于任意给定的网和起点,用PRIM算法的基本思想求解出所有的最小生成树并输出这些边的权值,所以如何实现输出显示所有的最小生成树关键问题所在,经过分析调试,用一个for语句就可以解决这个问题,从每个顶点出发,开始每一次遍历并输出显示出来。

算法的时间和空间性能分析

根据程序中算法的循环语句可以判断出普利姆算法的时间复杂度为O(n2)算法和图中的边数无关。因此普利姆算法适合求稠密网的最小生成树,因为在算法中用邻接矩阵的存储结构,在无向图中,邻接矩阵是对称的。所以仅需要存储上三角或下三角的元素,因此需要n(n+1)的存储空间。

测试结果

界面的截图

输入的情况的截图

输出结果的截图

输入错误的截图

七、源程序

#include

#include

#define inf 9999

#define max 40

#define linelenght 77

int adjg(int g[][max]) /* 建立无向图*/

{

int n,e,i,j,k,v1=0,v2=0,weight=0;

printf("Input the number of vertices, number of the edge:");

scanf("%d,%d",&n,&e);

while(e<=0||e>0.5*n*(n-1)||n>=max) /*最大边数为C n2,即0.5*n*(n-1)*/

{

error();

printf("Input the number of vertices, number of the edge:");

scanf("%d,%d",&n,&e);

}

for(i=1;i<=n;i++)

for(j=1;j<=n;j++)

g[i][j]=inf; /* 初始化矩阵,全部元素设为无穷大*/ for(k=1;k<=e;k++)

{

printf("Input the %d on the edge of the starting point, terminal, weights:",k);

scanf("%d,%d,%d",&v1,&v2,&weight);

while(v1==v2||v1>n||v2>n||v1<1||v2<1)

{

error();

printf("Input the %d on the edge of the starting point, terminal, weights:",k);

scanf("%d,%d,%d",&v1,&v2,&weight);

}

g[v1][v2]=weight; /* 无向网的邻接矩阵是对称矩阵*/

g[v2][v1]=weight;

}

return(n);

} /* 返回顶点个数n */

void pri(int g[][max],int n) /* 输出无向图的邻接矩阵*/

{

int i,j;

for(i=0;i<=n;i++)

printf("%d\t",i);

for(i=1;i<=n;i++)

{

printf("\n%d\t",i);

for(j=1;j<=n;j++) /* 输出边的权值*/

{

if(g[i][j]==inf) printf("%c\t",'\354');

else printf("%d\t",g[i][j]);

}

}

printf("\n");

}

void prim(int g[][max],int n) /* prim函数*/

{

int lowcost[max],closest[max];

int i,j,k,min;

for(i=2;i<=n;i++)

{ lowcost[i]=g[1][i]; /* 初始化*/

closest[i]=1;

}

lowcost[1]=0; /* 标志顶点1加入U集合*/ for(i=2;i<=n;i++) /* 形成n-1条边的生成树*/ {

min=inf;

k=0;

for(j=2;j<=n;j++) /* 寻找权值最小的一条边,并把权值赋给min */

if((lowcost[j]

{

min=lowcost[j];

k=j;

}

printf("(%d,%d)%d\t",closest[k],k,min);

lowcost[k]=0; /* 顶点k加入U */

for(j=2;j<=n;j++) /* 修改由顶点k到其他顶点边的权值*/

if(g[k][j]

{

lowcost[j]=g[k][j];

closest[j]=k;

}

printf("\n");

}

}

int priline(int h) /* 输出一条分割线*/

{

int g;

printf("\n|");

for(g=0;g

printf("*");

printf("|\n");

}

int error() /* 提示错误信息*/

{

printf("\n\n|************************E*R*R*O*R************************|\ n");

printf("Input errors or Data overflow!!! please re-enter\n\n");

fflush(stdin); /* 清除缓存*/

}

void main() /* 主函数*/

{

int g[max][max],n;priline(linelenght);

n=adjg(g);priline(linelenght);priline(linelenght);

printf("Input the adjacency matrix without directed graph:\n");

pri(g,n);

printf("\n");

printf("Minimum spanning tree structure:\n");

prim(g,n);

getch();

}

八、测试数据第一组

第二组

九、课程设计项目进度表及任务分配表及任务分配表

十、设计心得

陈娟:

此次的课程设计为:最小生成树的应用。主要包括三个部分。即:建立无向网,输出邻接矩阵,输出最小生成树(边和权值)。其中对于实现最小生成树我们用了prim算法。而prim算法也是此实验的重点和难点。其过程如下图:

此实验的prim算法用了较多的循环语句。让我对他们的使用有了更熟练的应用。

黄伟伟:

通过本次实验我学会了通过prime算法生成最小生成树的问题。所谓生成树,就是n个点之间连成n-1条边的图形。而最小生成树,就是权值(两点间直线的值)之和的最小值。首先,要用二维数组记录点和权值,然后再求最小生成树。具体方法是:1.先选取一个点作起始点,然后选择它邻近的权值最小的点(如果有多个与其相连的相同最小权值的点,随便选取一个)。2.再在伸延的点找与它邻近权值最小的点,与前一个已加入生成树的顶点。3.如此类推,当所有点都连同后,结果最生成树如上图所示。所有权值相加就是最小生成树。

谢贤根+陈开槟:

在做最小生成树的课程设计中,由于我知识掌握的不好,很多都需要同组队员的帮忙,让我了解到团结的力量。我们做事情,团结很重要,一个事件的是否顺利成功,往往需要团队中每天团员之间的相互帮助,互相配合。通过这次的课程设计实验,加强了我对最小生成树的理解,同时也对普利姆算法有了比较深刻的了解,而且,在实验的过程中,加强我的动手能力,虽说不能做的很好,但也有尽力而为了。本次实验也告诫了我要认真掌握书本的知识,多理解,并且要学会灵活应用书本的知识。

十一、参考文献

参考目录书

(1)求最小生成树,普里姆(Prim)算法- EdwardLewis的日志- 网易博客https://www.360docs.net/doc/4514631000.html,/zhoumhan_0351/blog/static/399542272009726111930478/

(2)严蔚敏,吴伟明。数据结构:c语言版。清华大学出版社,

(3) 严蔚敏数据结构与算法,百度视频

https://www.360docs.net/doc/4514631000.html,/programs/view/0I2eWUs5lK0/

学校地址:福建省武夷山市武夷大道16号设计单位:数学与计算机系

版本号:WyuKcsj Ver2007

数据结构课程设计报告java最小生成树

上海电力学院 数据结构(JAVA)课程设计 题目:____最小生成树_______ 学生姓名:_****___________ 学号:_____*******_______ 院系:计算机科学与技术学院 专业年级: ______*****___级 20**年 *月**日

目录 1.设计题目 (1) 2.需求分析 (1) 1)运行环境 (1) 2)输入的形式和输入值的范围 (1) 3)输出的形式描述 (1) 4)功能描述 (1) 5)测试数据 (1) 3.概要设计 (1) 1)抽象数据类型定义描述 (1) .2)功能模块设计 (1) 3)模块层次调用关系图 (2) 4.详细设计。实现概要设计中定义的所有的类的定义及类中成员函数,并对主要的模块写出伪码算法。 (2) 5.调试分析。包括调试过程中遇到的问题及解决的方法、算法的时间空间复杂性分析、经验体会。 (6) 6.用户使用说明。详细列出每一步的操作说明。 (7) 7. 测试结果 (7) 8.附录:程序设计源代码 (9)

一、设计题目 1).问题描述 若要在 n 个城市之间建设通信网络,只需要架设n-1 条线路即可。如何以最低的经济代价建设这个通信网,是一个网的最小生成树问题。 2). 基本要求 以邻接多重表存储无向带权图,利用克鲁斯卡尔算法或普瑞姆算法求网的最小生成树。 二、需求分析 1)运行环境 软件在JDK运行,硬件支持windows系统 2)输入的形式和输入值的范围 自动生成顶点数据在10~20之间;各个顶点之间权值在25~50之间;通过程序改动亦可生成已知顶点权值之间的最小生成树,需将随机生成代码改为edge edge[]={new edge(0,1,16),new(0,2,18)......}; 将已知顶点、权值通过其函数输入再生成其所对应最小生成树。 3)输出的形式描述 输出随机生成顶点个数以及各个顶点之间权值;然后输出本次生成顶点之间构成的最小生成树。

快速生成树的配置(思科)

快速生成树的配置(已经测试过) 实验名称:快速生成树配置。 实验目的:理解快速生成树配置及原理。 背景描述:现有两台交换机互连组成内部局域网,为了提高网络的可靠性,网络管理员用2 条链路将交换机互连,现要在交换机上做适当配置,使网络避免环路。 技术原理:生成树协议是利用SPA算法(生成树算法),在存在交换环路的网络中生成一个没有环路的树形网络。运用该算法将交换网络冗余的备份链路逻辑上断开,当主要链路出现故障时,能够自动 的切换到备份链路,保护数据的正常转发。 生成树协议目前常见的版本有STP(生成树协议IEEE802.1d)、RSTP(快速生成树协议IEE E802.1w)、MSTP(多生成树协议IEEE802.1s)。 实现功能:使网络在有冗余链路的情况下避免环路的产生,避免广播风暴等。 实验设备:S2126(2台);PC机(2台);直连线(4根) 实验拓扑: 按照拓扑图连接网络时注意,两台交换机都配置完快速生成树协议后,再将两台交换机连接起来。 如果先连接再配置会造成广播风暴,影响交换机的正常工作。

实验步骤: 步骤1:交换机A的基本配置。 SwitchA(config)#vlan 10 SwitchA(config-vlan)#name sales SwitchA(config-vlan)#exit SwitchA(config)#interface fastEthernet 0/3 SwitchA(config-if)#switchport access vlan 10 SwitchA(config-if)#end SwitchA#sh vlan id 10 VLAN Name Status Ports ---- -------------------------------- --------- --------- 10 sales active Fa0/3 SwitchA# 步骤2:在交换机A上配置快速生成树。 SwitchA(config)# spanning mode pvst SwitchA(config)#interface range fastethernet 0/1 SwitchA(config-if)#swit mode trunk SwitchA(config)#interface range fastethernet 0/2 SwitchA(config-if)#swit mode trunk SwitchA(config-if)#exit 步骤3:交换机B的基本配置。

最小生成树数据结构课程设计报告

河北科技大学 课程设计报告 学生姓名:白云学号:Z110702301 专业班级:计算机113班 课程名称:数据结构课程设计 学年学期: 2 01 3—2 014学年第2学期指导教师:郑广 2014年6月

课程设计成绩评定表

目录 一、需求分析说明 (1) 1.1最小生成树总体功能要求 (1) 1.2基本功能 (1) 1.3 模块分析 (1) 二、概要设计说明 (1) 2.1设计思路 (1) 2.2模块调用图 (2) 2.3数据结构设计 (2) 2.3.1.抽象数据类型 (2) 2.3.2方法描述 (2) 三、详细设计说明 (3) 3.1主函数模块 (3) 3.2邻接表输出子模块 (3) 3.3邻接矩阵输出子模块 (3) 3.4创建邻接矩阵子模块 (3) 3.5创建邻接表子模块 (3) 3.6 Prim子模块 (3) 3.7 Kruscal子模块 (4) 四、调试分析 (4) 4.1实际完成情况说明 (4) 4.2 出现的问题及解决方案 (4) 4.3程序中可以改进的地方 (4) 六、课程设计总结 (7) 七、测试数据 (7) 八、参考书目 (7)

一、需求分析说明 1.1最小生成树总体功能要求 在n个城市之间建设网络,只需保证连通即可,求最经济的架设方法。存储结构采用多种。求解算法多种。 1.2基本功能 在n个城市之间建设网络,只需要架设n-1条线路,建立最小生成树即可实现最经济的架设方法。 程序可利用克鲁斯卡尔算法或prim算法生成最小生成树。 1.3 模块分析 主模块:用于生成界面和调用各个子模块。 Kruscal模块:以kruscal算法实现最小生成树。 Prim模块:以prim算法实现最小生成树。 邻接表模块:用邻接表方式存储图。 邻接表输出模块:输出邻接表。 邻接矩阵模块:用邻接矩阵方式存储图。 邻接矩阵模块:输出邻接矩阵。 二、概要设计说明 2.1设计思路 问题的解决分别采用普利姆算法以及克鲁斯卡尔算法。 1) 普利姆算法就是先选择根,把它放入一个集合U中,剩余的顶点放在集合V中。然后选择该顶点与V中顶点之间权值最小的一条边,以此类推,如果达到最后一个则返回上一个顶点。 2) 克鲁斯卡尔算法就是写出所有的顶点,选择权最小的边,然后写出第二小的,以此类推,最终要有一个判断是否生成环,不生成则得到克鲁斯卡尔的最小生成树。

最小生成树问题的算法实现及复杂度分析—天津大学计算机科学与技术学院(算法设计与分析)

算法设计与分析课程设计报告 学院计算机科学与技术 专业计算机科学与技术 年级2011 姓名XXX 学号 2013年5 月19 日

题目:最小生成树问题的算法实现及复杂度分析 摘要:该程序操作简单,具有一定的应用性。数据结构是计算机科学的算法理论基础和软件设计的技术基础,在计算机领域中有着举足轻重的作用,是计算机学科的核心课程。而最小生成树算法是算法设计与分析中的重要算法,最小生成树也是最短路径算法。最短路径的问题在现实生活中应用非常广泛,如邮递员送信、公路造价等问题。本设计以Visual Studio 2010作为开发平台,C/C++语言作为编程语言,以邻接矩阵作为存储结构,编程实现了最小生成树算法。构造最小生成树有很多算法,本文主要介绍了图的概念、图的遍历,并分析了PRIM 经典算法的算法思想,最后用这种经典算法实现了最小生成树的生成。 引言:假设要在n个城市之间建立通信联络网,则连接n个城市只需要n-1条线路。这时,自然会考虑这样一个问题,如何在节省费用的前提下建立这个通信网?自然在每两个城市之间都可以设置一条线路,而这相应的就要付出较高的经济代价。n个城市之间最多可以设置n(n-1)/2条线路,那么如何在这些可能的线路中选择n-1 条使总的代价最小呢?可以用连通网来表示n 个城市以及n个城市之间可能设置的通信线路,其中网的顶点表示城市,边表示两个城市之间的线路,赋予边的权值表示相应的代价。对于n个顶点的连通网可以建立许多不同的生成树,每一个生成树都可以是一个通信网。现在要选择这样一棵生成树,也就是使总的代价最小。这个问题便是构造连通网的最小代价生成树(简称最小生成树)的问题。最小生成树是指在所有生成树中,边上权值之和最小的生成树,另外最小生成树也可能是多个,他们之间的权值之和相等。一棵生成树的代价就是树上各边的代价之和。而实现这个运算的经典算法就是普利姆算法。

生成树协议STP的应用实验1

实验四、生成树协议 STP的应用实验 【相关知识】 1.生成树协议 STP简介 在局域网中,为了提高网络连接可靠性,经常提供冗余链路。所谓冗余链路就像公路、铁路一 样,条条道路通北京,这条不通走那条。例如在大型企业网中,多半在核心层配置备份交换机(网 桥),则与汇聚层交换机形成环路,这样做使得企业网具备了冗余链路的安全优势。但原先的交换机 并不知道如何处理环路,而是将转发的数据帧在环路里循环转发,使得网络中出现广播风暴,最终 导致网络瘫痪。 为了解决冗余链路引起的问题, IEEE802 通过了 IEEE 802.1d协议, 即生成树协议 (Spanning Tree Protocol,STP)。IEEE 802.1d协议通过在交换机上运行一套复杂的算法,使冗余端口置于“阻塞状 ,从而使网络中的计算机通信时只有一条链路生效,而当这个链路出现故障时,STP 将会重新计 态” 算出网络的最优链路,将“阻塞状态”的端口重新打开,从而确保网络连接的稳定可靠。 生成树协议和其它协议一样,是随着网络的不断发展而不断更新换代的。在生成树协议发展的 过程中,老的缺陷不断被克服,新的特性不断被开发出来。按照功能特点的改进情况,习惯上生成 树协议的发展过程被分为三代: 第一代生成树协议:STP/RSTP 第二代生成树协议:PVST/PVST+ 第三代生成树协议:MISTP/MSTP 2.IEEE 801.1D生成树协议简介 生成树协议(Spanning Tree Protocol,STP)最初是由美国数字设备公司(DEC)开发的,后经 IEEE 修改并最终制定了 IEEE 802.1d标准。 STP 协议的主要思想是当网络中存在备份链路时,只允许主链路激活,如果主链路失效,备份 链路才会被打开。大家知道,自然界中生长的树是不会出现环路的,如果网络也能够像树一样生长 就不会出现环路。STP 协议的本质就是利用图论中的生成树算法,对网络的物理结构不加改变,而 在逻辑上切断环路,封闭某个网桥,提取连通图,形成一个生成树,以解决环路所造成的严重后果。 为了理解生成树协议,必先了解以下概念: (1)桥协议数据单元(Bridge Protocol Data Unit,BPDU):交换机通过交换 BPDU来获得建立 最佳树型拓扑结构所需的信息。生成树协议运行时, 交换机使用共同的组播地址 “01-80-C2-00-00-00”来发送 BPDU; (2)每个交换机有唯一的桥标识符(Brideg ID),由桥优先级和 MAC 地址组成; (3)每个交换机的端口有唯一的端口标识符(Port ID),由端口优先级和端口号组成; (4)对生成树的配置时,对每个交换机配置一个相对的优先级,对每个交换机的每个端口也配 置一个相对的优先级,该值越小优先级越高; (5)具有最高优先级的交换机被称为根桥(Root Bridge),如果所有设备都具有相同的优先级, 则具有最低 MAC 地址的设备将成为根桥; (6)网络中每个交换机端口都有一个根路径开销(Root Path Cost),根路径开销是某交换机到 根桥所经过的路径开销(与链路带宽有关)的总和; (7)根端口是各个交换机通往根桥的根路径开销最低的端口,若有多个端口具有相同的根路径 开销,则端口标识符小的端口为根端口; (8)在每个 LAN 中都有一个交换机被称为指定交换机(Designated Bridge),它是该 LAN 中与 根桥连接而且根路径开销最低的交换机; (9)指定交换机和 LAN 连接的端口被称为指定端口(Designated Port)。如果指定桥中有两个 以上的端口连在这个 LAN 上,则具有最高优先级的端口被选为指定端口。根桥上的端口都可以成为

贪心算法实验(最小生成树)

算法分析与设计实验报告第一次附加实验

附录: 完整代码(贪心法) //贪心算法最小生成树prim算法 #include #include #include #include #include using namespace std; #define inf 9999; //定义无限大的值const int N=6; template //模板定义 void Prim(int n,Type c[][N+1]); int main() { int c[N+1][N+1]; cout<<"连通带权图的矩阵为:"<

cin>>c[i][j]; } } cout<<"Prim算法最小生成树选边次序如下:"< //参数为结点个数n,和无向带权图中各结点之间的距离c[][N+1] void Prim(int n,Type c[][N+1]) { Type lowcost[N+1]; //记录c[j][closest]的最小权值 int closest[N+1]; //V-S中点j在s中的最临接顶点 bool s[N+1]; //标记各结点是否已经放入S集合| s[1]=true; //初始化s[i],lowcost[i],closest[i] for(int i=2;i<=n;i++) { lowcost[i]=c[1][i]; closest[i]=1; s[i]=false; } for(int i=1;i

最小生成树实验报告

数据结构课程设计报告题目:最小生成树问题 院(系):计算机工程学院 学生姓名: 班级:学号: 起迄日期: 指导教师: 2011—2012年度第 2 学期 一、需求分析 1.问题描述:

在n个城市之间建设网络,只需保证连通即可,求最经济的架设方法。存储结构采用多种。求解算法多种。 2.基本功能 在n个城市之间建设网络,只需要架设n-1条线路,建立最小生成树即可实现最经济的架设方法。 程序可利用克鲁斯卡尔算法或prim算法生成最小生成树。 3.输入输出 以文本形式输出最小生成树,同时输出它们的权值。通过人机对话方式即用户通过自行选择命令来输入数据和生成相应的数据结果。 二、概要设计 1.设计思路: 因为是最小生成树问题,所以采用了课本上介绍过的克鲁斯卡尔算法和 prim算法两种方法来生成最小生成树。根据要求,需采用多种存储结构,所以我选择采用了邻接表和邻接矩阵两种存储结构。 2.数据结构设计: 图状结构: ADT Graph{ 数据对象V:V是具有相同特性的数据元素的集合,称为顶点集。 数据关系R:R={VR} VR={|v,w∈V且P(v,w),表示从v到w的弧, 谓词P(v,w)定义了弧的意义或信息} 基本操作: CreateGraph( &G, V, VR ) 初始条件:V是图的顶点集,VR是图中弧的集合。 操作结果:按V和VR的定义构造图G。 DestroyGraph( &G )

初始条件:图G存在。 操作结果:销毁图G。 LocateVex( G, u ) 初始条件:图G存在,u和G中顶点有相同特征。 操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返 回其它信息。 GetVex( G, v ) 初始条件:图G存在,v是G中某个顶点。 操作结果:返回v的值。 PutVex( &G, v, value ) 初始条件:图G存在,v是G中某个顶点。 操作结果:对v赋值value。 FirstAdjVex( G, v ) 初始条件:图G存在,v是G中某个顶点。 操作结果:返回v的第一个邻接顶点。若顶点在G中没有邻接顶点, 则返回“空”。 NextAdjVex( G, v, w ) 初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点。 操作结果:返回v的(相对于w的)下一个邻接顶点。若w是v的 最后一个邻接点,则返回“空”。 InsertVex( &G, v ) 初始条件:图G存在,v和图中顶点有相同特征。 操作结果:在图G中增添新顶点v。 DeleteVex( &G, v ) 初始条件:图G存在,v是G中某个顶点。 操作结果:删除G中顶点v及其相关的弧。 InsertArc( &G, v, w )

最小生成树算法分析

最小生成树算法分析 一、生成树的概念 若图是连通的无向图或强连通的有向图,则从其中任一个顶点出发调用一次bfs或dfs后便可以系统地访问图中所有顶点;若图是有根的有向图,则从根出发通过调用一次dfs或bfs亦可系统地访问所有顶点。在这种情况下,图中所有顶点加上遍历过程中经过的边所构成的子图称为原图的生成树。 对于不连通的无向图和不是强连通的有向图,若有根或者从根外的任意顶点出发,调用一次bfs或dfs后一般不能系统地访问所有顶点,而只能得到以出发点为根的连通分支(或强连通分支)的生成树。要访问其它顶点需要从没有访问过的顶点中找一个顶点作为起始点,再次调用bfs 或dfs,这样得到的是生成森林。 由此可以看出,一个图的生成树是不唯一的,不同的搜索方法可以得到不同的生成树,即使是同一种搜索方法,出发点不同亦可导致不同的生成树。 可以证明:具有n个顶点的带权连通图,其对应的生成树有n-1条边。 二、求图的最小生成树算法 严格来说,如果图G=(V,E)是一个连通的无向图,则把它的全部顶点V和一部分边E’构成一个子图G’,即G’=(V, E’),且边集E’能将图中所有顶点连通又不形成回路,则称子图G’是图G的一棵生成树。 对于加权连通图,生成树的权即为生成树中所有边上的权值总和,权值最小的生成树称为图的最小生成树。 求图的最小生成树具有很高的实际应用价值,比如下面的这个例题。

例1、城市公交网 [问题描述] 有一张城市地图,图中的顶点为城市,无向边代表两个城市间的连通关系,边上的权为在这两个城市之间修建高速公路的造价,研究后发现,这个地图有一个特点,即任一对城市都是连通的。现在的问题是,要修建若干高速公路把所有城市联系起来,问如何设计可使得工程的总造价最少。 [输入] n(城市数,1<=n<=100) e(边数) 以下e行,每行3个数i,j,w ij,表示在城市i,j之间修建高速公路的造价。 [输出] n-1行,每行为两个城市的序号,表明这两个城市间建一条高速公路。 [举例] 下面的图(A)表示一个5个城市的地图,图(B)、(C)是对图(A)分别进行深度优先遍历和广度优先遍历得到的一棵生成树,其权和分别为20和33,前者比后者好一些,但并不是最小生成树,最小生成树的权和为19。 [问题分析] 出发点:具有n个顶点的带权连通图,其对应的生成树有n-1条边。那么选哪n-1条边呢?设图G的度为n,G=(V,E),我们介绍两种基于贪心的算法,Prim算法和Kruskal算法。 1、用Prim算法求最小生成树的思想如下: ①设置一个顶点的集合S和一个边的集合TE,S和TE的初始状态均为空集; ②选定图中的一个顶点K,从K开始生成最小生成树,将K加入到集合S; ③重复下列操作,直到选取了n-1条边: 选取一条权值最小的边(X,Y),其中X∈S,not (Y∈S); 将顶点Y加入集合S,边(X,Y)加入集合TE; ④得到最小生成树T =(S,TE)

最小生成树在旅游路线选择中的应用概况

编号: 审定成绩: 重庆邮电大学研究生堂下考试答卷 2013-2014学年第1 学期论文题目:最小生成树在旅游路线选择中的应用 学院名称: 学生姓名: 专业: 学号: 指导教师: 重庆邮电大学教务处制

摘要 随着生活节奏的加快,人民生活水平的提高,人们越来越热衷于四处旅游,同时,大家也不愿意将大部分的时间花费在路途上,人们旅游目的在于放松、赏景、游玩,旅游公司就不得不根据游客要求做出相应的旅游路线安排。很多旅游景点之间都相隔一定的距离,那么如何在众多旅游景点路线中选择最近的一条呢?因此,如何做到即保证游览各个景点又确保路途最近地从众多可行路线中选出最优路线成为了解决此问题的关键。 图论最小生成树理论常用于交通线路选择中,本文将其运用于旅游交通优化与线路组织上,即在赋权图中找出一颗最优树,以满足以最短路径最小连接各旅游目的城市和最小的建设成本。我们所学《图论及其算法》教材中介绍了其中的三种算法Prim 算法、Kruskal 算法和破圈法。本文涉及的抽象图形结构较为简单,使用各类算法的差别在此并无明显体现,一般来说,Kruskal 算法应用较为普遍,因此本文采用Kruskal 算法实现最优路径求取。 文中通过一个例子应用,将最小生成树的Kruskal 算法实际化,通过算法步骤分析,以及在VC++6.0中程序的运行,最终求出的最小生成树与实际相符,该算法思想成立,并具有一般性,能够增删节点、修改权值,也可运用到其他问题的解决中。 关键词:旅游路线问题 Kruskal算法最优路线最小生成树

一、引言 旅游交通是为旅游者由客源地到旅游目的地的往返,以及在旅游目的地各处旅游活动而提供的交通设施及服务,其便利程度,是衡量旅游业发达程度的重要标志。与一般交通不同,旅游交通过程本身也是旅游体验过程,对于游客来说,立足于最小的时间与经济成本获得最多的旅游体验,对于旅游组织者来说,则立足于最小的建设成本与最大的社会、经济、生态效益。道路是交通的载体,具有高度通达性、完善的旅游服务功能和景观化、生态化、人性化的道路是区域旅游交通完善的重要标志,基于此,有学者提出“风景道”、“旅游交通干道”等规划建设理念与原则。其中,旅游交通系统的优化很大程度取决于合理的道路布局,而如何使道路通达性与建设成本之间获得平衡,达到性价比最优,成为道路系统优化的重要指标。因此,其实质上可以简化为最短距离连接各旅游目的地最优解问题[1]。 旅游路线组织是旅游地理学研究的重要内容,其研究主要以游客的行为空间模式为导向,旅游路线是旅游产品的组成部分,作为产品就必须满足游客的需求,因此游客的行为模式就成为旅游路线设计的重要依据。 二、背景知识 1、图和树 图论中的图是由若干给定的点及连接两点的线所构成的图形,这种图形通常用来描述某些事物之间的某种特定关系,用点代表事物,用连接两点的线表示相应两个事物间具有这种关系。树是无圈连通无向图,如果树T的节点数为n,那么树的边数为n-1。 2、生成树 连通图G 上的一个子图,该子图连通,无回路且包含图G 的所有节点,称为连通图的极小连通子图。一个连通图可以有多棵不同的生成树。 3、最小生成树 对一个带权连通图,也有多可不同的生成树。由于该图是带权图,各边的权值不一定相等,因此这些生成树的各边权值之和也不一定相同,其中权值最小的生成树被称为该带权连通图的最小生成树[4]。 三、最小生成树的求解方法 构造最小生成树可以有多种算法。我们所学《图论及其算法》教材中介绍了其中的三种算法Prim 算法、Kruskal 算法和破圈法,本文分别用这三种算法来实现最小生成树的构造。

最小生成树问题中北大学数据结构课程设计资料

中北大学 数据结构与算法课程设计 说明书 学院、系:软件学院 专业:软件工程 班级: 学生姓名:学号: 设计题目:最小生成树问题 起迄日期: 2015年1月12日- 2015年1月29日指导教师:王秀娟 2015 年1月 29 日

1需求分析 1.1已知一个无向连通网表示n个城市以及城市间可能设置的通信网络线路,其中网的顶点表示城市,边表示两个城市之间的线路,赋于边上的权值表示相应的代价。对于n个点的连通网能建立许多不同的生成树,每一棵生成树都可以是一个通信网。我们要选择一棵生成树,使总的耗费最小。 1.2该无向连通图的建立需要使用两种存储结构,即邻接表和邻接矩阵。 1.3实现最小生成树需要使用两种算法。即普里姆算法和克鲁斯卡尔。 1.4程序通过人机交互实现数据的输入和输出。 2选题要求 设计内容: 在n个城市之间建设网络,只需保证连通即可,求最经济的架设方法。存储结构采用(邻接表和邻接矩阵)两种,采用课本上的两种求解算法。 设计要求: (1) 符合课题要求,实现相应功能; (2) 要求界面友好美观,操作方便易行; (3) 注意程序的实用性、安全性。 3程序设计方法及主要函数介绍 ADT Graph{ 数据对象V;V是具有相同特性的数据元素的集合,成为顶点集。 数据关系R: R = {VR} VR = {(v,w)|v,w为V集合中的元素,(v,w)表示v和w之间存在的路径} 基本操作P; CreateMGraph(MGraph *G) 初始条件:V是图的顶点集,VR是图的边的集合。 操作结果:按V和VR的定义构造图G,用邻接矩阵存储。 CreateALGraph(ALGraph *G)

kruskal算法求最小生成树

#include #include #include #include using namespace std; #define maxn 110 //最多点个数 int n, m; //点个数,边数 int parent[maxn]; //父亲节点,当值为-1时表示根节点 int ans; //存放最小生成树权值 struct eage //边的结构体,u、v为两端点,w为边权值

{ int u, v, w; }EG[5010]; bool cmp(eage a, eage b) //排序调用 { return a.w < b.w; } int Find(int x) //寻找根节点,判断是否在同一棵树中的依据 { if(parent[x] == -1) return x; return Find(parent[x]); } void Kruskal() //Kruskal算法,parent能够还原一棵生成树,或者森林{ memset(parent, -1, sizeof(parent)); sort(EG+1, EG+m+1, cmp); //按权值将边从小到大排序 ans = 0; for(int i = 1; i <= m; i++) //按权值从小到大选择边 { int t1 = Find(EG[i].u), t2 = Find(EG[i].v); if(t1 != t2) //若不在同一棵树种则选择该边,合并两棵树 { ans += EG[i].w; parent[t1] = t2; printf("最小生成树加入的边为:%d %d\n",EG[i].u,EG[i].v); } } } int main() { printf("输入顶点数和边数:"); while(~scanf("%d%d", &n,&m)) { for(int i = 1; i <= m; i++) scanf("%d%d%d", &EG[i].u, &EG[i].v, &EG[i].w); Kruskal(); printf("最小生成树权值之和为:%d\n", ans); } return 0; }

徐州工程学院数据结构最小生成树实验文档

实验九图的最小生成树算法的实现 实验预备知识: 1.理解图最小生成树的意义和相应算法。 2.掌握带权图的存储结构。 一、实验目的 1.使学生熟悉最小生成树的算法实现。 2.掌握带权图的存储结构和处理方法。 二、实验环境 ⒈硬件:每个学生需配备计算机一台。操作系统:DOS或Windows; ⒉软件:DOS或Windows操作系统+Turbo C; 三、实验要求 1.能够独立完成带权图的存储和最小生成树的生成 四、实验内容 1.在自己的U盘的“姓名+学号”文件夹中创建“实验9”文件夹,本次实验的所有程序和数据都要求存储到本文件夹中。 2.现在某电信公司要对如下图的几个城市之间进行光纤连接布线,请用合适的存储结构将下图存储到计算机中方便进行处理。 3.现在公司想以最小的代价将所有城市连通,方便所有城市间通信,请用普里姆算法和克鲁斯卡尔算法实现本图的最小生成树

#include #include #define INF 50 typedef struct ArcNode{ int adjvex; //该弧所指向的顶点位置struct ArcNode *nextarc; //下一个临接点 int weight; //弧的权重 }ArcNode; //表结点 typedef struct VNode{ char data; //顶点信息 ArcNode *firstarc; //指向下一个结点 }VNode,AdjList[6]; typedef struct{ AdjList LH; //创建头结点数组 int vexnum; //图的点的个数 int arcnum; //图的边的个数 }Graph; typedef struct{ char nextvex; int lowcost; int know; }Auxiliary_array; //辅助数组结构体 void main (void){ void buildtu (Graph*); void printgraph(Graph*); void prim( Graph *G, char u); char u; Graph UDG; Graph *G = &UDG; buildtu(G); printgraph(G); //打印图 printf("请输入起始顶点:\n"); while(getchar()!='\n'); u = getchar();

最小生成树经典算法

最小生成树的两种经典算法的分析及实现 摘要:数据结构是计算机科学的算法理论基础和软件设计的技术基础,在计算机领域中有着举足轻重的作用,是计算机学科的核心课程。构造最小生成树有很多算法,本文主要介绍了图的概念、图的遍历,并分析了PRIM和KRUSKAL的两种经典算法的算法思想,对两者进行了详细的比较,最后用这两种经典算法实现了最小生成树的生成。 关键词:连通图,赋权图,最小生成树,算法,实现 1 前言 假设要在n个城市之间建立通信联络网,则连接n个城市只需要n-1条线路。这时,自然会考虑这样一个问题,如何在节省费用的前提下建立这个通信网?自然在每两个城市之间都可以设置一条线路,而这相应的就要付出较高的经济代价。n个城市之间最多可以设置n (n-1)/2条线路,那么如何在这些可能的线路中选择n-1 条使总的代价最小呢?可以用连通网来表示n 个城市以及n个城市之间可能设置的通信线路,其中网的顶点表示城市,边表示两个城市之间的线路,赋予边的权值表示相应的代价。对于n个顶点的连通网可以建立许多不同的生成树,每一个生成树都可以是一个通信网。现在要选择这样一棵生成树,也就是使总的代价最小。这个问题便是构造连通网的最小代价生成树(简称最小生成树)的问题。一棵生成树的代价就是树上各边的代价之和。 2图的概念 2.1 定义 无序积 在无序积中, 无向图,其中为顶点(结点)集,为边集,,中元素为无向边,简称边。 有向图,其中为顶点(结点)集,为边集,,中元素为有向边,简称边。 有时,泛指有向图或无向图。 2.2 图的表示法

有向图,无向图的顶点都用小圆圈表示。 无向边——连接顶点的线段。 有向边——以为始点,以为终点的有向线段。 2.3 概念 (1)有限图——都是有限集的图。 阶图——的图。 零图——的图。特别,若又有,称平凡图。 (2)关联 (边与点关系)——设边(或),则称与(或)关联。 无环 孤立点——无边关联的点。 环——一条边关联的两个顶点重合,称此边为环 (即两顶点重合的边)。 悬挂点——只有一条边与其关联的点,所对应的边叫悬挂边。 (3)平行边——关联于同一对顶点的若干条边称为平行边。平行边的条数称为重数。 多重图——含有平行边的图。 简单图——不含平行边和环的图。 2.4 完全图 设为阶无向简单图,若中每个顶点都与其余个顶点相邻,则 称为阶无向完全图,记作。 若有向图的任一对顶点,既有有向边,又有有向边,则 称为有向完全图。 例如:

大数据结构课程设计-最小生成树

《数据结构》期末课程设计 题目第8题:最小生成树问题学院计算机学院 专业 班别 学号 姓名陈聪 2015年7月6日

一、需求分析 1、问题描述 若要在n个城市之间建设通讯网络,只需要架设n-1条线路即可。如何以最低的经济代价建设这个通讯网,是一个网的最小生成树问题。 2、基本要求 (1)利用克鲁斯卡尔算法求网的最小生成树。 (2)实现并查集。以此表示构造生成树过程中的连通分量。 (3)以文本形式输出生成树中各条边以及他们的权值。 3、实现提示 通讯线路一旦建立,必然是双向的。因此,构造最小生成树的网一定是无向网。设图的顶点数不超过30个,并为简单起见,网中边的权值设成小于100的整数,可利用C语言提供的随机数函数产生。 图的存储结构的选取应和所作操作向适应。为了便于选择权值最小的边,此题的存储结构既不选用邻接矩阵的数组表示法,也不选用邻接表,而是以存储边(带权)的数组即边集数组表示图。 二、详细设计 根据课设题目要求,拟将整体程序分为三大模块,分别是:图的存储结构,并查集的实现,克鲁斯卡尔算法的实现。 1、边集数组的类型定义: typedef struct { int x, y; int w; }edge; x表示起点,y表示终点,w为权值。 2、并查集功能的实现由以下函数实现: Make_Set(int x)初始化集合; Find_Set(int x) 查找x元素所在的集合,回溯时压缩路径; Union(int x, int y, int w)合并x,y所在的集合。

3、克鲁斯卡尔算法的实现 该算法的实现位于主函数中: qsort(e, n, sizeof(edge), cmp); //将边排序 printf("最小生成树的各条边及权值为:\n"); for (i = 0; i < n; i++) { x = Find_Set(e[i].x); y = Find_Set(e[i].y); if (x != y ) { printf("%c - %c : %d\n", e[i].x + 'A', e[i].y + 'A', e[i].w); Union(x, y, e[i].w); } } 4、设计中还包含以下函数: (1)/* 比较函数,按权值(相同则按x坐标)非降序排序*/ int cmp(const void *a, const void *b) { if ((*(edge *)a).w == (*(edge *)b).w) { return (*(edge *)a).x - (*(edge *)b).x; } return (*(edge *)a).w - (*(edge *)b).w; } (2)快排函数qsort,包含在stdlib.h头文件里 qsort(e, n, sizeof(edge), cmp); (3)C语言提供的随机数函数srand( unsigned int seed ); 使用随机数函数如下: srand( (unsigned)time( NULL ) ); for( i = 0; i < n;i++ )

最小生成树(Prim、Kruskal算法)整理版

一、树及生成树的基本概念 树是无向图的特殊情况,即对于一个N个节点的无向图,其中只有N-1条边,且图中任意两点间有且仅有一条路径,即图中不存在环,这样的图称为树,一般记为T。树定义有以下几种表述: (1)、T连通、无圈、有n个结点,连通有n-1条边;(2)、T无回路,但不相邻的两个结点间联以一边,恰得一个圈;(3)、T连通,但去掉任意一边,T就不连通了(即在点集合相同的图中,树是含边数最少的连通图);(4)、T的任意两个结点之间恰有一条初等链。 例如:已知有六个城市,它们之间要架设电话线,要求任 意两个城市均可以互相通话,并且电话线的总长度最短。若用 六个点v1…v6代表这六个城市,在任意两个城市之间架设电话 线,即在相应的两个点之间连一条边。这样,六个城市的一个 电话网就作成一个图。任意两个城市之间均可以通话,这个图 必须是连通图,且这个图必须是无圈的。否则,从圈上任意去 掉一条边,剩下的图仍然是六个城市的一个电话网。图5-6是 一个不含圈的连通图,代表了一个电话线网。 生成树(支撑树) 定义:如果图G’是一棵包含G的所有顶点的树,则称G’是G的一个支撑树或生成树。例如,图5-7b是图5-7a的一个支撑树。 定理:一个图G有生成树的条件是G是连通图。 证明:必要性显然; 充分性:设图G是连通的,若G不含圈,则按照定义,G是一个树,从而G是自身的一个生成树。若G含圈,则任取G的一个圈,从该圈中任意去掉一条边,得到图G的一生成子图G1。若G1不含圈,则G1是G的一个生成树。若G1仍然含圈,则任取G1的一个圈,再从圈中任意去掉一条边,得到图G的一生成子图G2。依此类推,可以得到图G的一个生成子 图G K,且不含圈,从而G K是一个生成树。 寻找连通图生成树的方法: 破圈法:从图中任取一个圈,去掉一条边。再对剩下的图 重复以上步骤,直到不含圈时为止,这样就得到一个生成树。 取一个圈(v1,v2,v3,v1),在一个圈中去掉边e3。在剩下的图 中,再取一个圈(v1,v2,v4,v3,v1),去掉边e4。再从圈(v3,v4,v5,v3) 中去掉边e6。再从圈(v1,v2,v5,v4,v3,v1)中去掉边e7, 这样,剩下的图不含圈,于是得到一个支撑树,如图所示。 避圈法:也称为生长法,从图中某一点开始生长边,逐步扩展成长为一棵树,每步选取与已入树的边不构成圈的那些边。

最小生成树的应用

武 夷 学 院 课程设计报告 课程名称: 数据结构(C 言语版本) 设计题目: 最小生成树的应用 学生班级: 10计科1班 学生姓名: 陈娟,谢贤根,黄伟伟,陈开槟 指导教师: 林丽惠 完成日期: 2012-01-05

课程设计项目研究报告 目录 一、问题描述及基本要求....................................................................................... - 1 - 二、实现本程序需要解决的问题如下................................................................. - 1 - 三、测试数据......................................................................................................... - 2 - 四、算法思想......................................................................................................... - 3 - 五、模块划分............................................................................ 错误!未定义书签。 六、算法设计与分析............................................................................................. - 7 - 七、源程序........................................................................................................... - 11 - 八、测试数据....................................................................................................... - 14 - 九、课程设计项目进度表及任务分配表及任务分配表................................... - 15 - 十、设计心得....................................................................................................... - 16 -十一参考文献....................................................................................................... - 17 -

最小生成树的Kruskal算法实现

#include #include #define M 20 #define MAX 20 typedef struct { int begin; int end; int weight; }edge; typedef struct { int adj; int weight; }AdjMatrix[MAX][MAX]; typedef struct { AdjMatrix arc; int vexnum, arcnum; }MGraph; void CreatGraph(MGraph *);//函数申明 void sort(edge* ,MGraph *); void MiniSpanTree(MGraph *); int Find(int *, int ); void Swapn(edge *, int, int); void CreatGraph(MGraph *G)//构件图 { int i, j,n, m; printf("请输入边数和顶点数:\n"); scanf("%d %d",&G->arcnum,&G->vexnum); for (i = 1; i <= G->vexnum; i++)//初始化图{ for ( j = 1; j <= G->vexnum; j++) { G->arc[i][j].adj = G->arc[j][i].adj = 0; } } for ( i = 1; i <= G->arcnum; i++)//输入边和权值

{ printf("请输入有边的2个顶点\n"); scanf("%d %d",&n,&m); while(n < 0 || n > G->vexnum || m < 0 || n > G->vexnum) { printf("输入的数字不符合要求请重新输入:\n"); scanf("%d%d",&n,&m); } G->arc[n][m].adj = G->arc[m][n].adj = 1; getchar(); printf("请输入%d与%d之间的权值:\n", n, m); scanf("%d",&G->arc[n][m].weight); } printf("邻接矩阵为:\n"); for ( i = 1; i <= G->vexnum; i++) { for ( j = 1; j <= G->vexnum; j++) { printf("%d ",G->arc[i][j].adj); } printf("\n"); } } void sort(edge edges[],MGraph *G)//对权值进行排序{ int i, j; for ( i = 1; i < G->arcnum; i++) { for ( j = i + 1; j <= G->arcnum; j++) { if (edges[i].weight > edges[j].weight) { Swapn(edges, i, j); } } } printf("权排序之后的为:\n"); for (i = 1; i < G->arcnum; i++) {

相关文档
最新文档