使用C语言实现最小生成树求解的简单方法_C 语言

最小生成树Prim算法朴素版
有几点需要说明一下。

1、2个for循环都是从2开始的,因为一般我们默认开始就把第一个节点加入生成树,因此之后不需要再次寻找它。

2、lowcost[i]记录的是以节点i为终点的最小边权值。初始化时因为默认把第一个节点加入生成树,因此lowcost[i] = graph[1][i],即最小边权值就是各节点到1号节点的边权值。

3、mst[i]记录的是lowcost[i]对应的起点,这样有起点,有终点,即可唯一确定一条边了。初始化时mst[i] = 1,即每条边都是从1号节点出发。

编写程序:对于如下一个带权无向图,给出节点个数以及所有边权值,用Prim算法求最小生成树。

输入数据:

7 11
A B 7
A D 5
B C 8
B D 9
B E 7
C E 5
D E 15
D F 6
E F 8
E G 9
F G 11

输出:

A - D : 5
D - F : 6
A - B : 7
B - E : 7
E - C : 5
E - G : 9
Total:39

最小生成树Prim算法朴素版 C语言实现 代码如下

#include <stdio.h>
#include <stdlib.h>

#define MAX 100
#define MAXCOST 0x7fffffff

int graph[MAX][MAX];

int Prim(int graph[][MAX], int n)
{
 /* lowcost[i]记录以i为终点的边的最小权值,当lowcost[i]=0时表示终点i加入生成树 */
 int lowcost[MAX];

 /* mst[i]记录对应lowcost[i]的起点,当mst[i]=0时表示起点i加入生成树 */
 int mst[MAX];

 int i, j, min, minid, sum = 0;

 /* 默认选择1号节点加入生成树,从2号节点开始初始化 */
 for (i = 2; i <= n; i++)
 {
 /* 最短距离初始化为其他节点到1号节点的距离 */
 lowcost[i] = graph[1][i];

 /* 标记所有节点的起点皆为默认的1号节点 */
 mst[i] = 1;
 }

 /* 标记1号节点加入生成树 */
 mst[1] = 0;

 /* n个节点至少需要n-1条边构成最小生成树 */
 for (i = 2; i <= n; i++)
 {
 min = MAXCOST;
 minid = 0;

 /* 找满足条件的最小权值边的节点minid */
 for (j = 2; j <= n; j++)
 {
  /* 边权值较小且不在生成树中 */
  if (lowcost[j] < min && lowcost[j] != 0)
  {
  min = lowcost[j];
  minid = j;
  }
 }
 /* 输出生成树边的信息:起点,终点,权值 */
 printf("%c - %c : %d\n", mst[minid] + 'A' - 1, minid + 'A' - 1, min);

 /* 累加权值 */
 sum += min;

 /* 标记节点minid加入生成树 */
 lowcost[minid] = 0;

 /* 更新当前节点minid到其他节点的权值 */
 for (j = 2; j <= n; j++)
 {
  /* 发现更小的权值 */
  if (graph[minid][j] < lowcost[j])
  {
  /* 更新权值信息 */
  lowcost[j] = graph[minid][j];

  /* 更新最小权值边的起点 */
  mst[j] = minid;
  }
 }
 }
 /* 返回最小权值和 */
 return sum;
}

int main()
{
 int i, j, k, m, n;
 int x, y, cost;
 char chx, chy;

 /* 读取节点和边的数目 */
 scanf("%d%d", &m, &n);
 getchar();

 /* 初始化图,所有节点间距离为无穷大 */
 for (i = 1; i <= m; i++)
 {
 for (j = 1; j <= m; j++)
 {
  graph[i][j] = MAXCOST;
 }
 }

 /* 读取边信息 */
 for (k = 0; k < n; k++)
 {
 scanf("%c %c %d", &chx, &chy, &cost);
 getchar();
 i = chx - 'A' + 1;
 j = chy - 'A' + 1;
 graph[i][j] = cost;
 graph[j][i] = cost;
 }

 /* 求解最小生成树 */
 cost = Prim(graph, m);

 /* 输出最小权值和 */
 printf("Total:%d\n", cost);

 //system("pause");
 return 0;
}

Kruskal算法:

void Kruskal(Edge E[],int n,int e)
{
 int i,j,m1,m2,sn1,sn2,k;
 int vset[MAXE];
 for (i=0;i<n;i++) vset[i]=i; //初始化辅助数组
 k=1;          //k表示当前构造最小生成树的第几条边,初值为1
 j=0;          //E中边的下标,初值为0
 while (k<n)      //生成的边数小于n时循环
 {
  m1=E[j].u;m2=E[j].v;    //取一条边的头尾顶点
 sn1=vset[m1];sn2=vset[m2]; //分别得到两个顶点所属的集合编号
 if (sn1!=sn2)    //两顶点属于不同的集合,该边是最小生成树的一条边
 {
  printf(" (%d,%d):%d/n",m1,m2,E[j].w);
  k++;          //生成边数增1
  for (i=0;i<n;i++)    //两个集合统一编号
   if (vset[i]==sn2)  //集合编号为sn2的改为sn1
       vset[i]=sn1;
 }
 j++;     //扫描下一条边
 }
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索c语言
最小生成树
最小生成树c语言代码、最小生成树prim c语言、c语言最小生成树算法、c语言最小生成树、c语言求最小生成树,以便于您获取更多的相关知识。

时间: 2024-10-25 09:12:20

使用C语言实现最小生成树求解的简单方法_C 语言的相关文章

在C++中自定义宏的简单方法_C 语言

可以使用宏定义没有返回值的"函数".例如:   复制代码 代码如下: #define PrintMax(a, b) \   do \   { \     int x = a, y = b; \     printf("Max: %d\n", x > y ? x : y);\   } while (0) // ... PrintMax(3, 4);     这样的"函数"与真正意义上的函数有本质的区别,因为宏是一个编译前行为,仅仅是编译前对文

c语言实现词频统计的简单实例_C 语言

需求: 1.设计一个词频统计软件,统计给定英文文章的单词频率. 2.文章中包含的标点不计入统计. 3.将统计结果以从大到小的排序方式输出. 设计: 1.因为是跨专业0.0···并不会c++和java,只能用仅学过的C语言进行编写,还是挺费劲的. 2.定义一个包含单词和频率两个成员的结构体来统计词频(进行了动态分配内存,可以处理较大文本). 3.使用fopen函数读取指定的文档. 4.使用fgetc函数获取字符,再根据取得的字符是否是字母进行不同的处理. 5.采用快速排序法对统计结果进行排序. 5

提高C++程序运行效率的10个简单方法_C 语言

本文以C/C++程序为例讲述了程序运行效率的10个简单方法,分享给大家供大家参考之用.具体分析如下: 对于每一个程序员来说,程序的运行效率都是一个值得重视,并为之付出努力的问题.但是程序性能的优化也是一门复杂的学问,需要很多的知识,然而并不是每个程序员都具备这样的知识,而且论述如何优化程序提高程序运行效率的书籍也很少.但是这并不等于我们可以忽略程序的运行效率,下面就介绍一下本人积累的一些简单实用的提高程序运行效率的方法,希望对大家有所帮助. 一.尽量减少值传递,多用引用来传递参数.至于其中的原因

使用C语言求N的阶乘的方法_C 语言

用递归法求N的阶乘 程序调用自身称为递归( recursion).它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解. 递归的能力在于用有限的语句来定义对象的无限集合. 一般来说,递归需要有边界条件.递归前进段和递归返回段.当边界条件不满足时,递归前进:当边界条件满足时,递归返回. #include <stdio.h> #include <string.h> #include <stdlib.h> long factorial(int n) {

C语言实现BMP转换JPG的方法_C 语言

本文实例讲述了C语言实现BMP转换JPG的方法.分享给大家供大家参考.具体实现方法如下: /**************************************************************************** 名称: jpeg.c 功能: linux下bmp转化为jpeg程序源代码 日期: 2010.01.26 注意: 编译时加"-ljpeg"(gcc -o bmp2jpg jpeg.c -ljpeg) ***********************

C语言打印华氏-摄氏温度对照表的方法_C 语言

本文实例讲述了C语言打印华氏-摄氏温度对照表的方法.分享给大家供大家参考.具体实现方法如下: /* * 打印华氏-摄氏温度对照表 */ #include <stdio.h> /* 温度上限 */ #define MIN 20.0 /* 温度下限 */ #define MAX 300.0 /* 步长 */ #define BC 20.0 main() { /* 定义温度及上下限步常变量 */ float oc,of=1.0; /* 打印标题 */ printf("华氏-摄氏温度对照表\

C语言实现字母大小写转换的方法_C 语言

本文实例讲述了C语言实现字母大小写转换的方法.分享给大家供大家参考.具体实现方法如下: /* * 将大写字母转换为小写字母 */ #include <stdio.h> int lower(int c) { return ((c>='A')&&(c<='z'))?(c+'a'-'A'):(c); } main() { int i; char a[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; for(i=0;i<26;i++)

C语言中查询进程信号是否被遮罩或搁置的简单方法_C 语言

C语言sigprocmask()函数:查询或设置信号遮罩头文件: #include <signal.h> 定义函数: int sigprocmask(int how, const sigset_t *set, sigset_t * oldset); 函数说明:sigprocmask()可以用来改变目前的信号遮罩, 其操作依参数how 来决定: 1.SIG_BLOCK 新的信号遮罩由目前的信号遮罩和参数set 指定的信号遮罩作联集 2.SIG_UNBLOCK 将目前的信号遮罩删除掉参数set 指

C语言中对字母进行大小写转换的简单方法_C 语言

C语言tolower()函数:将大写字母转换为小写字母头文件: #include <ctype.h> 定义函数: int toupper(int c); 函数说明:若参数 c 为小写字母则将该对应的大写字母返回. 返回值:返回转换后的大写字母,若不须转换则将参数c 值返回. 范例:将s 字符串内的小写字母转换成大写字母. #include <ctype.h> main(){ char s[] = "aBcDeFgH12345;!#$"; int i; print