接昨天,在这里给出图的其中一种应用:最小生成树算法(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. MySQL8.0 redo日志系统优化

    背景 现在主流的数据库系统的故障恢复逻辑都是基于经典的ARIES协议,也就是基于undo日志+redo日志的来进行故障恢复.redo日志是物理日志,一般采用WAL(Write-Ahead-Loggin ...

  2. [考试反思]0926csp-s模拟测试52:审判

    也好. 该来的迟早会来. 反思再说吧. 向下跳过直到另一条分界线 %%%cbx也拿到了他的第一个AK了呢. 我的还是遥不可及. 我恨你,DeepinC. 我恨透你了.你亲手埋葬所有希望,令我无比气愤. ...

  3. 雷神领域(并查集真是个好东西)并查集+流氓dp

    考场上,整整看了半个小时以上的题目!!! 化简题意: 给定一个全0矩阵,一些坐标点(x,y)为1,当三个点可以构成一个直角三角形时(直角边长为整数)拓展为一个矩形,之后从(0,0)出发,求最多的占用行 ...

  4. CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths——dsu on tree

    题目描述 一棵根为1 的树,每条边上有一个字符(a-v共22种). 一条简单路径被称为Dokhtar-kosh当且仅当路径上的字符经过重新排序后可以变成一个回文串. 求每个子树中最长的Dokhtar- ...

  5. 代码托管服务平台GitHub

    GitHub 可以托管各种 git 库,并提供一个 Web 界面,但与其它像 SourceForge 或 Google Code 这样的服务不同,GitHub 的独特卖点在于从另外一个项目进行分支的简 ...

  6. springboot使用dubbo和zookeeper

    2019-11-17 yls 创建服务接口模块 接口工程只提供接口,不提供实现,在后面的提供者和消费者中使用 在使用接口的模块中只需要写具体实现类,避免了在每个模块中重复编写接口 在接口中引入依赖包 ...

  7. C++对象模型结论

    C++对象模型 1.C++对象模型探讨的是对象成员存储问题. 2.结论: (1) .类内部的函数(静态成员函数,非静态成员函数)都不在对象内部 ,不占用对象大小. (2) 类内部的静态变量不占用对象大 ...

  8. nyoj 412 Same binary weight ()

    Same binary weight 时间限制:300 ms  |  内存限制:65535 KB 难度:3   描述 The binary weight of a positive  integer ...

  9. shodan 文档学习笔记

    Table of Contents 1. Introduction 1.1. All About the Data 1.2. Data Collection 1.3. SSL in Depth 1.3 ...

  10. Java内存模型与volatile关键字

    Java内存模型与volatile关键字 一).并发程序开发 并行程序的开发要涉及多线程.多任务间的协作和数据共享问题. 常用的并发控制:内部锁.重入锁.读写锁.信号量. 二).线程的特点 线程的特点 ...