视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
计算机算法设计与分析 最小生成树 实验报告
2025-10-03 14:37:52 责编:小OO
文档
×××学院实验报告纸

计算机科学与工程学院( 院、系)网络工程  专业 071 班  组 计算机算法设计与分析 课

学号 200710224133     姓名121  实验日期  2010.            教师评定           

最小生成树问题

1、实验目的:

通过简单的实际应用例子,了解和掌握最小生成树问题的要点和方法。

2、算法分析:

设计思想:

  图的存储使用数组表示法,即邻接矩阵存储,结构体包含图的邻接矩阵,当前顶点数和弧数。图的初始化使用二重循环得到顶点和表的权值,邻接矩阵的打印使用二重for循环。然后把图各边的权值按从小到大排序;然后依次把最小边加入进来,即生成最小生成树。

克鲁斯卡尔算法:假设 WN=(V,{E}) 是一个含有 n 个顶点的连通网,按照构造最小生成树的过程为:先构造一个只含 n 个顶点,而边集为空的子图,之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至只有一棵树,也即子图中含有 n-1条边为止。

1、设定图的抽象数据类型:

ADT Graph{

数据对象V:V是具有相同特性的数据元素的集合,称为点集.

数据关系R:

R={VR}

VR={(v,w)|v,w属于V,(v,w)表示v和w之间存在的路径}

基本操作P:

CreatGraph(&G,V,VR)

初始条件:V是图的顶点集,VR是图中弧的集合.

操作结果:按V和VR是定义构造图G.

Sort(edge* ,MGraph *)

初始条件: 图G存在,各边权值已知;

操作结果:对权值进行排序;

Find(int *, int )

初始条件:前者为已存在的集合,后者为集合中的元素;

操作结果:查找函数,确定后者所属子集;

MiniSpanTree(MGraph *)

初始条件: 图G存在,各边权值已知;

操作结果:生成最小树;

      Swapn(edge *, int, int)

      初始条件: 图G存在,各边权值已知;

操作结果:交换某两个边的权值;

2 图的存储结构

typedef struct

{

 int adj;

 int weight;

}AdjMatrix[MAX][MAX];

typedef struct

{

 AdjMatrix arc;

 int vexnum, arcnum;

}MGraph;

typedef struct 

{

 int begin;

 int end;

 int weight;

}edge;

3 本程序包含的模块

}

1)初始化操作,结构体定义;

2)函数声明模块;

3)函数定义模块;

4)主程序模块

  Main()

{

调用函数生成图;

判断图是否为空;(空则从新输入)

调用函数生成最小生成树;

退出;

3、程序代码:

#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("请输入边数和顶点数:");

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("\\n请输入有边的2个顶点");

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

while(n < 0 || n > G->vexnum || m < 0 || n > G->vexnum)

  {

   printf("输入的数字不符合要求 请重新输入:");

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

  }

     

G->arc[n][m].adj = G->arc[m][n].adj = 1;

  getchar();

  printf("\\n请输入%d与%d之间的权值:", 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++)

 {

printf("<< %d, %d >> %d\\n", edges[i].begin, edges[i].end, edges[i].weight);

 }

}

void Swapn(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 MiniSpanTree(MGraph *G)

{

 int i, j, n, m;

 int k = 1;

    int parent[M];

 edge edges[M];

 

for ( i = 1; i < G->vexnum; i++)

 {

for (j = i + 1; j <= G->vexnum; j++)

  {

if (G->arc[i][j].adj == 1)

   {

    edges[k].begin = i;

    edges[k].end = j;

edges[k].weight = G->arc[i][j].weight;

       k++;

   }

   

  }

 }

        

    sort(edges, G);

for (i = 1; i <= G->arcnum; i++)

 {

  parent[i] = 0;

 }

    printf("最小生成树为:\\n");

for (i = 1; i <= G->arcnum; i++)

 {

  n = Find(parent, edges[i].begin);

  m = Find(parent, edges[i].end);

  if (n != m)

  {

     parent[n] = m;

printf("<< %d, %d >> %d\\n", edges[i].begin, edges[i].end, edges[i].weight);

  }

 }

}

int Find(int *parent, int f)

{

while ( parent[f] > 0)

 {

  f = parent[f];

 }

    return f;

}

int main(void)

{

 MGraph *G;

 G = (MGraph*)malloc(sizeof(MGraph));

 if (G == NULL)

 {

  printf("memory allcation failed,goodbye");

  exit(1);

 }

    

 CreatGraph(G);

    MiniSpanTree(G);

   

 system("pause");

 return 0;

4、时间复杂度分析:

   由于在图的初始化以及邻接矩阵的打印时均使用了循环的嵌套,故其时间复杂度为 O(n2 )的;其他操作的时间复杂度均为O(1)。

5、总结:

通过一个简单的实际例子,比较好地掌握了最小生成树的算法思想。下载本文

显示全文
专题