接昨天,在这里给出图的其中一种应用:最小生成树算法(Prime算法和Kruskal算法)。两种算法的区别就是:Prime算法以顶点为主线,适合用于顶点少,边密集的图结构;Kruskal算法以边为主线,适合于顶点比较多,但是边比较稀疏的图结构。代码如下,亲测,可执行,在最后也给出输入数据的形式。

 /*
图结构的最小生成树算法:
1.prime算法:按顶点查找,遍历当前顶点所有邻接边,选择权值最小值,
记录这两个顶点,直到所有的顶点都已处理 2.Kruskal算法:按边查找,将所有边的权值排序,以此选择权值最小的边,
检查该边连接的两个顶点是否状态一致(都已处理,或都未处理),
直到所有顶点都标记为处理过
*/ #include<stdio.h>
#define INFINITY 65535
#define MAXVEX 100 //边集数组图结构
typedef struct //边结构体
{
int start;
int end;
int weight;
}Edges; typedef struct //图结构
{
char Vex[MAXVEX]; //顶点数组
Edges edge[MAXVEX]; //边数组
int numVexes; //顶点数量
int numEdges; //边数量
}E_VGraph; //邻接矩阵图结构
typedef struct
{
char Vex[MAXVEX]; //顶点数组
int arc[MAXVEX][MAXVEX]; //边数组
int numVexes; //顶点数量
int numEdges; //边数量
}Graph; //邻接矩阵图结构转化为边集数组图结构,并将权值升序排序
void G_EVConversion(Graph G, E_VGraph *G1)
{
int i,j,k,lowest;
Edges edges[MAXVEX];
G1->numVexes = G.numVexes; //将邻接矩阵顶点数赋值于边集数组
G1->numEdges = G.numEdges; //将邻接矩阵边数赋值于边集数组
for(i = ; i < G.numVexes; i++) //遍历邻接矩阵中的每个顶点
{
for(j = i+; j < G.numVexes; j++) //遍历除当前结点之后的结点
{
if(G.arc[i][j] != INFINITY) //判断两顶点之间是否有边
{
edges[i].start = i; //记录当前边的起点
edges[i].end = j; //记录当前边的终点
edges[i].weight = G.arc[i][j]; //记录当前边的权重
printf("%d %d\n",G.arc[i][j],edges[i].weight);
}
}
}
printf("\n\n");
for(i = ; i < G.numEdges; i++) //选择排序edges数组
{
lowest = INFINITY;
for(j = ; j < G.numEdges; j++)
{
printf("%d %d %d\n",j,edges[j].weight,lowest);
if(edges[j].weight <= lowest)
{
lowest = edges[j].weight;
k = j;
printf("\n%d\n",k);
}
}
G1->edge[i].start = edges[k].start; //将每轮找出的最小权值的边的信息
G1->edge[i].end = edges[k].end; //写入边集数组中
G1->edge[i].weight = edges[k].weight;
edges[k].weight = INFINITY; //赋值完毕,将此最小权值设为最大值
printf("\n");
printf("%d\n",G1->edge[i].weight);
}
} //确认函数
int Find(int *parent, int f)
{
if(parent[f] > ) //检查此顶点是否处理过,若大于0,则处理过
f = parent[f]; //将parent[f]的值赋值给f
return f; //返回f
} //克鲁斯卡尔算法构造最小生成树
void minTreeKruskal(E_VGraph G1)
{
int i,j,k,w,n,m;
int parent[MAXVEX]; //记录结点状态
int lowest = ; //最小权值
for(i = ; i < G1.numVexes; i++) //初始化记录数组,所有顶点记为未被处理
parent[i] = ;
for(i = ; i < G1.numEdges; i++) //遍历边集数组
{
n = Find(parent, G1.edge[i].start); //得到当前边的开始顶点的状态
m = Find(parent, G1.edge[i].end); //得到当前边的结束顶点的状态
if(n != m) //若状态不同(即,起点与终点一个处理过,一个未处理)
{
lowest += G1.edge[i].weight; //将此边的权值加入最小生成树权值
parent[G1.edge[i].start] = ; //将起点记为处理过
parent[G1.edge[i].end] = ; //将终点记为处理过
}
}
printf("克鲁斯卡尔算法构建最小生成树的权值为:%d\n", lowest);
} void CreatGraph(Graph *G) //创建图结构
{
int i,j,k,w,a[];
printf("请输入顶点与边的数量:");
scanf("%d,%d",&G->numVexes,&G->numEdges); //写入顶点数量与边的数量
for(i = ; i < G->numVexes; i++) //初始化顶点数组
{
printf("请输入第%d个顶点:", i);
scanf("%c",&G->Vex[i]);
getchar();
}
for(i = ; i < G->numVexes; i++) //初始化边数组
for(j = ; j < G->numVexes; j++)
G->arc[i][j] = INFINITY; for(k = ; k < G->numEdges; k++) //构造边的数组
{
printf("请输入边的起点与终点的下标及其权重:");
scanf("%d,%d,%d",&i,&j,&w);
G->arc[i][j] = G->arc[j][i] = w; //无向图的对称性
}
printf("创建成功\n");
} //Prim算法构造最小生成树
void minTreePrim(Graph G,int i)
{
int j,k,l,w,count,zongWeight;
int visited[MAXVEX]; //记录访问过的顶点
int lowest[MAXVEX]; //记录最小权值
for(j = ; j < G.numVexes; j++) //初始化访问数组,将所有顶点记为未访问过
visited[j] = ;
visited[i] = ; //将传入顶点记为访问过
lowest[i] = ; //将此顶点的权值记为0
zongWeight = ; //总权重为0
count = ; //访问过的顶点数量为1
int wei = INFINITY; //权重变量记为最大值
while(count < G.numVexes) //只要访问过的顶点数目小于图中顶点数目,继续循环
{
for(k = ; k < G.numVexes; k++) //遍历访问过的顶点数组
{
if(visited[k] == ) //如果当前顶点访问了,寻找它的邻接边
{
for(l = ; l < G.numVexes; l++) //遍历图中所有顶点
{
if(visited[l] == && G.arc[k][l] < wei) //如果未被访问,且权值小于权值变量
{
wei = G.arc[k][l]; //更新权值变量
w = l; //更新最小顶点
}
}
}
}
visited[w] = ; //将最小权值顶点记为访问过
lowest[l] = wei; //记录他的权值
zongWeight += wei; //加入总权重
count++; //访问过的顶点数量+1
wei = INFINITY; }
printf("最小生成树的权值为:%d\n",zongWeight);
} void main()
{
Graph G;
E_VGraph G1; printf("请构造图结构:\n");
CreatGraph(&G); printf("\n\n");
printf("普利姆算法构建最小生成树\n");
minTreePrim(G,); printf("\n\n");
printf("克鲁斯卡尔算法构建最小生成树\n");
G_EVConversion(G, &G1);
minTreeKruskal(G1);
}

本来今天应该将最小生成树与最短路径的算法一起上传,但是我写的最短路径算法还有一些bug没调好,所以要延迟一天,勿怪。

最小生成树与最短路径--C语言实现的更多相关文章

  1. 加权图的最小生成树、最短路径算法 - java实现

    加权图相关算法 前言 本文主要介绍加权图算法中两个重要应用:最小生成树和最短路径. 求最小生成树时针对的是加权无向图,加权有向图的最小生成树算法成为"最小属树形图"问题,较为复杂, ...

  2. C数据结构(文件操作,随机数,排序,栈和队列,图和遍历,最小生成树,最短路径)程序例子

    文件操作 文件打开方式               意义     ”r” 只读打开一个文本文件,只允许读数据     ”w” 只写打开或建立一个文本文件,只允许写数据     ”a” 追加打开一个文本 ...

  3. 最小生成树(prime算法 & kruskal算法)和 最短路径算法(floyd算法 & dijkstra算法)

    一.主要内容: 介绍图论中两大经典问题:最小生成树问题以及最短路径问题,以及给出解决每个问题的两种不同算法. 其中最小生成树问题可参考以下题目: 题目1012:畅通工程 http://ac.jobdu ...

  4. 最小生成树——Prim算法和Kruskal算法

    洛谷P3366 最小生成树板子题 这篇博客介绍两个算法:Prim算法和Kruskal算法,两个算法各有优劣 一般来说当图比较稀疏的时候,Kruskal算法比较快 而当图很密集,Prim算法就大显身手了 ...

  5. 25最短路径之Dijkstra算法

    图的最优化问题:最小生成树.最短路径 典型的图应用问题 无向连通加权图的最小生成树 有向/无向加权图的最短路径 四个经典算法 Kruskal算法.Prim算法---------------最小生成树 ...

  6. 23最小生成树之Kruskal算法

    图的最优化问题:最小生成树.最短路径 典型的图应用问题 无向连通加权图的最小生成树 有向/无向加权图的最短路径 四个经典算法 Kruskal算法.Prim算法---------------最小生成树 ...

  7. 算法笔记_119:蓝桥杯第六届省赛(Java语言A组)试题解答

     目录 1 熊怪吃核桃 2 星系炸弹 3 九数分三组 4 循环节长度 5 打印菱形 6 加法变乘法 7 牌型种数 8 移动距离 9 垒骰子 10 灾后重建   前言:以下试题解答代码部分仅供参考,若有 ...

  8. 7-10 公路村村通(30 分)(最小生成树Prim算法)

    7-10 公路村村通(30 分) 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N(≤1 ...

  9. ACM比赛技巧

    一.语言是最重要的基本功   无论侧重于什么方面,只要是通过计算机程序去最终实现的竞赛,语言都是大家要过的第一道关.亚洲赛区的比赛支持的语言包括C/C++与JAVA.笔者首先说说JAVA,众所周知,作 ...

随机推荐

  1. 中小学生试卷自动生成程序--jialin大佬代码分析

    结对编程代码评价 有幸和小jialin结对编程.拿到jialin的代码后. 我先是尝试用idea运行.结果报了如下错误. 无法加载主类,再尝试用eclipse运行. 好的,可以运行,那为什么用idea ...

  2. CF464D World of Darkraft - 2

    Roma 在游戏"World of Darkraft"(理论上应该是 World of darkcraft,MineCraft 的一个版本)找到一个新角色. \(\mathrm{R ...

  3. Asp.net Core 系列之--2.ORM初探:Dapper实现MySql数据库各类操作

    ChuanGoing 2019-09-10 距离上一篇近一个月时间,断断续续才把本篇码完,后面将加快进度,争取年度内把本系列基本介绍完成,同时督促本人持续学习. 本篇学习曲线: 1.初识Dapper ...

  4. 映客直播软开校招岗(go语言)

    问题: 笔试: 比较简单,有一道题比较深刻: 内存1G,需要计算1G的数据排序,哪种排序方法效率最低,当时选的是冒泡,因为涉及到频繁的数据交换,其实应该是归并,因为归并不是原地排序,多占用的内存空间, ...

  5. go中的数据结构接口-interface

    1. 接口的基本使用 golang中的interface本身也是一种类型,它代表的是一个方法的集合.任何类型只要实现了接口中声明的所有方法,那么该类就实现了该接口.与其他语言不同,golang并不需要 ...

  6. nyoj 26-孪生素数问题(打表)

    26-孪生素数问题 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:10 submit:43 题目描述: 写一个程序,找出给出素数范围内的所有孪生素数 ...

  7. nyoj 56-阶乘因式分解(一)(数学)

    56-阶乘因式分解(一) 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:15 submit:16 题目描述: 给定两个数m,n,其中m是一个素数. ...

  8. 五分钟学会HTML5的WebSocket协议

    1.背景   很多网站为了实现推送技术,所用的技术都是Ajax轮询.轮询是在特定的的时间间隔由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器.这种传统的模式带来很明显的缺点 ...

  9. 接口测试之-postman

    在使用postman进行接口测试的时候,对于有些接口字段需要时间戳加密,这个时候我们就遇到2个问题,其一是接口中的时间戳如何得到?其二就是对于现在常用的md5加密操作如何在postman中使用代码实现 ...

  10. CSS如何设置列表样式属性,看这篇文章就够用了

    列表样式属性 在HTML中有2种列表.无序列表和有序列表,在工作中无序列表比较常用,无序列表就是ul标签和li标签组合成的称之为无序列表,那什么是有序列表呢?就是ol标签和li标签组合成的称之为有序列 ...