接昨天,在这里给出图的其中一种应用:最小生成树算法(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. [UWP] 为WinRT组件创建Nuget包

    Nuget 是 dotnet 开发中必不可少的包管理工具,但不仅仅局限于 dotnet 项目,在 VS 中使用 C++ 开发的时候,也可以使用 Nuget 来引用第三方组件.同样也可以用 Nuget ...

  2. AtCoder Grand Contest 036 A-C

    目录 \(\bf A - Triangle\) \(\bf B - Do\ Not\ Duplicate\) \(\bf C - GP 2\) \(\bf D - Negative \ Cycle\) ...

  3. NOIP模拟 19

    最近试考的脑壳疼 晚上还有一场555 T1 count 研究性质题. 研究好了AC,研究不明白就没头绪 首先枚举n的因子d 其次发现因为是树,所以如果合法,贡献只能是1 然后发现如果合法,一定是一棵一 ...

  4. python——字符串操作函数

    字符串 join() map() split() rsplit() splitlines() partiton() rpartition() upper() lower() swapcase() ca ...

  5. java中的线程安全

    在Java中,线程的安全实际上指的是内存的安全,这是由操作系统决定的. 目前主流的操作系统都是多任务的,即多个进程同时运行.为了保证安全,每个进程只能访问分配给自己的内存空间,而不能访问别的.分配给别 ...

  6. 本周授课内容:http,https,Tomcat,servlet

    https:https是基于安全套接字的http协议,也可以理解为是http+ssl/tls(数字证书)的组合 http和https的区别: HTTP 的 URL 以 http:// 开头,而 HTT ...

  7. Jenkins初体验-安装与部署服务

    一.概述 1.简介 在工作中接触到CD/CI,Devops相关的技术,本文记录Jenkins的基本使用.Jenkins是一款开源的持续集成工具,能够集成一套自动化部署任务. 目标 通过jenkins从 ...

  8. ES6学习笔记01 -- 暂时性死区 ( temporal dead zone )

    参考文档: let 和 const 命令 - ECMAScript6入门  暂时性死区(temporal dead zone) 理解ES6中的TDZ(暂时性死区) ES6 中 let 暂时性死区详解 ...

  9. Algorithm: GCD、EXGCD、Inverse Element

    数论基础 数论是纯数学的一个研究分支,主要研究整数的性质.初等数论包括整除理论.同余理论.连分数理论.这一篇主要记录的是同余相关的基础知识. 取模 取模是一种运算,本质就是带余除法,运算结果就是余数. ...

  10. 技术人如何利用 github+Jekyll ,搭建一个独立免费的技术博客

    上次有人留言说,技术博客是程序员的标配,但据我所知绝大部分技术同学到现在仍然没有自己的技术博客.原因有很多,有的是懒的写,有的是怕写不好,还有的是一直想憋个大招,幻想做到完美再发出来,结果一直胎死腹中 ...