最小生成树与最短路径--C语言实现
接昨天,在这里给出图的其中一种应用:最小生成树算法(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语言实现的更多相关文章
- 加权图的最小生成树、最短路径算法 - java实现
加权图相关算法 前言 本文主要介绍加权图算法中两个重要应用:最小生成树和最短路径. 求最小生成树时针对的是加权无向图,加权有向图的最小生成树算法成为"最小属树形图"问题,较为复杂, ...
- C数据结构(文件操作,随机数,排序,栈和队列,图和遍历,最小生成树,最短路径)程序例子
文件操作 文件打开方式 意义 ”r” 只读打开一个文本文件,只允许读数据 ”w” 只写打开或建立一个文本文件,只允许写数据 ”a” 追加打开一个文本 ...
- 最小生成树(prime算法 & kruskal算法)和 最短路径算法(floyd算法 & dijkstra算法)
一.主要内容: 介绍图论中两大经典问题:最小生成树问题以及最短路径问题,以及给出解决每个问题的两种不同算法. 其中最小生成树问题可参考以下题目: 题目1012:畅通工程 http://ac.jobdu ...
- 最小生成树——Prim算法和Kruskal算法
洛谷P3366 最小生成树板子题 这篇博客介绍两个算法:Prim算法和Kruskal算法,两个算法各有优劣 一般来说当图比较稀疏的时候,Kruskal算法比较快 而当图很密集,Prim算法就大显身手了 ...
- 25最短路径之Dijkstra算法
图的最优化问题:最小生成树.最短路径 典型的图应用问题 无向连通加权图的最小生成树 有向/无向加权图的最短路径 四个经典算法 Kruskal算法.Prim算法---------------最小生成树 ...
- 23最小生成树之Kruskal算法
图的最优化问题:最小生成树.最短路径 典型的图应用问题 无向连通加权图的最小生成树 有向/无向加权图的最短路径 四个经典算法 Kruskal算法.Prim算法---------------最小生成树 ...
- 算法笔记_119:蓝桥杯第六届省赛(Java语言A组)试题解答
目录 1 熊怪吃核桃 2 星系炸弹 3 九数分三组 4 循环节长度 5 打印菱形 6 加法变乘法 7 牌型种数 8 移动距离 9 垒骰子 10 灾后重建 前言:以下试题解答代码部分仅供参考,若有 ...
- 7-10 公路村村通(30 分)(最小生成树Prim算法)
7-10 公路村村通(30 分) 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N(≤1 ...
- ACM比赛技巧
一.语言是最重要的基本功 无论侧重于什么方面,只要是通过计算机程序去最终实现的竞赛,语言都是大家要过的第一道关.亚洲赛区的比赛支持的语言包括C/C++与JAVA.笔者首先说说JAVA,众所周知,作 ...
随机推荐
- 【XSY2525】Maze 2017多校
Description 考虑一个 N×M 的网格,每个网格要么是空的,要么是障碍物.整个网格四周都是墙壁(即第1行和第n行,第1列和第m列都是墙壁),墙壁有且仅有两处开口,分别代表起点和终点.起点总是 ...
- CSPS模拟 69
$C_n^0=1$ $C_n^0=1$ $C_n^0=1$ 我怎么又双叒叕犯这种错误了啊 (咳檀) T1 WA0,大神题,不会做! T2 就是要找一个最长区间,满足左端点是区间最小值,右端点是区间最大 ...
- margin:0 auto为何会居中?
margin: 0 auto;为何会居中呢??? 一开始的学习html的时候,就是只知道块级元素margin:0 auto就能居中 但是后来就很好奇 margin: auto 0;为何不能垂直居中? ...
- ORACLE存储过程的创建和执行的简单示例和一些注意点
此示例的主要目的主要是为了了解在PL/SQL环境下怎么创建和执行存储过程. 存储过程所涉及的DataTable: 第一步:创建游标变量 游标是ORACLE系统在内存中开辟的一个工作区,主要用来存储SE ...
- vue的相关知识
一.DOM vs 函数库 vs框架 DOM: API繁琐 函数库:JQuery对DOM的每个步骤的API进行一对一的简化,但并没有改变DOM做事的步骤和方法. 框架:一个包含部分已经实现的功能的半成 ...
- CSS(6)---通俗讲解浮动(float)
CSS(6)---通俗讲解浮动(float) CSS有三模块:盒子模型.浮动 .定位.上篇博客有讲到 盒子模型地址:CSS(5)---通俗讲解盒子模型 一.理解浮动 1.概念 概念 浮动可以理解为让某 ...
- 深入理解计算机系统 第十章 系统级I/O
很多高级语言都提供了执行 I/O 的较高级别的函数.为什么我们还要学习 Unix I/O? 原因:1.由于 I/O 和其他系统概念之间有循环依赖关系,故了解 Unix I/O 将帮助我们理解其他的系统 ...
- C++中对C的扩展学习新增语法——For循环以及AUTO类型
For循环以及AUTO类型 For代码实现: AUTO类型: 1.auto自动类型推导,省事. 2.auto主要在模板中用的多,模板的类型比较长,使用auto可以简化代码. 3.不要轻易使用,我们在编 ...
- 自学python的高效学习方法【python秘籍】
随着互联网的发展,数据科学概念的普及,Python火得一塌糊涂,为此很多小伙伴想学这门语言,苦于没有正确的学习方法,大部分都放弃了,所以我想总结下经验来帮助大家高效学完python技术!第一.首先学习 ...
- pat 1042 Shuffling Machine(20 分)
1042 Shuffling Machine(20 分) Shuffling is a procedure used to randomize a deck of playing cards. Bec ...