克鲁斯卡尔(Kruskal)算法

  1 # include <stdio.h>
  2
  3 # define MAX_VERTEXES 100//最大顶点数
  4 # define MAXEDGE 20//边集数组最大值
  5 # define INFINITY 65535//代表不可能的数(无穷大)
  6
  7 typedef struct
  8 {//图 结构体定义
  9     int arc[MAX_VERTEXES][MAX_VERTEXES];//二位数组 矩阵
 10     int numVertexes, numEdges;//当前图中的顶点数和边数
 11
 12 }MGraph;
 13
 14 typedef struct
 15 {//边集数组 结构体定义
 16     int begin;
 17     int end;
 18     int weight;
 19
 20 }Edge;
 21
 22 void CreateMGraph (MGraph *G)
 23 {//创建
 24      int i, j;
 25      //下面是已经输入好的
 26      G->numVertexes = 9;
 27      G->numEdges = 15;
 28
 29      for (i=0; i<G->numVertexes; i++)
 30          for (j=0; j<G->numVertexes; j++)
 31              if (i == j)
 32                  G->arc[i][j] = 0;
 33              else
 34                  G->arc[i][j] = G->arc[j][i] = INFINITY;
 35
 36     G->arc[0][1]=10;
 37     G->arc[0][5]=11;
 38     G->arc[1][2]=18;
 39     G->arc[1][8]=12;
 40     G->arc[1][6]=16;
 41     G->arc[2][8]=8;
 42     G->arc[2][3]=22;
 43     G->arc[3][8]=21;
 44     G->arc[3][6]=24;
 45     G->arc[3][7]=16;
 46     G->arc[3][4]=20;
 47     G->arc[4][7]=7;
 48     G->arc[4][5]=26;
 49     G->arc[5][6]=17;
 50     G->arc[6][7]=19;
 51
 52     for (i=0; i<G->numVertexes; i++)
 53         for (j=i+1; j<G->numVertexes; j++)//矩阵的上三角,然后对称矩阵的下三角
 54             G->arc[j][i]  = G->arc[i][j];//对称
 55 }
 56
 57 void swapn (Edge *edges, int i, int j)
 58 {//交换权值
 59     int temp;
 60
 61     //起始
 62     temp = edges[i].begin;
 63     edges[i].begin = edges[j].begin;
 64     edges[j].begin = temp;
 65
 66     //结束
 67     temp = edges[i].end;
 68     edges[i].end = edges[j].end;
 69     edges[j].end = temp;
 70
 71     //权值
 72     temp = edges[i].weight;
 73     edges[i].weight = edges[j].weight;
 74     edges[j].weight = temp;
 75
 76     return ;
 77 }
 78
 79 void sort (Edge edges[], MGraph *G)
 80 {//对权值进行排序
 81     int i, j;
 82     for (i=0; i<G->numEdges; i++)
 83         for (j=i+1; j<G->numEdges; j++)//对存入有效边(两端点的权值)进行冒泡排序
 84             if (edges[i].weight > edges[j].weight)
 85                 swapn (edges, i, j);//交换权值
 86
 87     printf ("排序过后:\n");
 88     for (i=0; i<G->numEdges; i++)
 89         printf ("边:(%d,%d) 权值:%d\n", edges[i].begin, edges[i].end, edges[i].weight);
 90
 91     return ;
 92 }
 93
 94 int Find (int *parent, int f)//★
 95 {// 查找连线顶点的尾部下标
 96 //走过的路都有记录,如果走已经走过的路的话,那么返回的值(n=m);
 97     while (parent[f] > 0)
 98         f = parent[f];
 99     return f;
100 }
101
102 void MiniSpanTree_Kruskal (MGraph G)
103 {//克鲁斯卡尔算法
104     int i, j, n, m;
105     int k = 0;
106     int parent[MAX_VERTEXES];//定义一维数组判断是否形成环路
107     Edge edges[MAXEDGE];//定义边集数组
108
109     for (i=0; i<G.numVertexes; i++)//存储有效的边(两个端点和权值)
110         for (j=i+1; j<G.numVertexes; j++)//矩阵上三角进行比较,因为对称,所以比较一半更节约时间
111             if (G.arc[i][j] < INFINITY)
112             {
113                 edges[k].begin = i;
114                 edges[k].end = j;
115                 edges[k ++].weight = G.arc[i][j];
116             }
117     sort(edges, &G);//排序
118
119     for (i=0; i<G.numVertexes; i++)
120         parent[i] = 0;
121
122     printf ("\n打印最小生成树:\n");
123     for (i=0; i<G.numEdges; i++)
124     {
125         n = Find (parent, edges[i].begin);//★
126         m = Find (parent, edges[i].end);//★
127         if (n != m)
128         {
129             parent[n] = m;
130             printf ("边(%d,%d) 权值:%d\n", edges[i].begin, edges[i].end, edges[i].weight);
131         }
132     }
133 }
134
135 int main (void)
136
137 {
138     MGraph G;
139     CreateMGraph (&G);//创建
140     MiniSpanTree_Kruskal (G);//克鲁斯卡尔 算法
141
142     return 0;
143 }
144
145 /*
146 在vc++6.0运行结果:
147
148     排序过后:
149     边:(4,7) 权值:7
150     边:(2,8) 权值:8
151     边:(0,1) 权值:10
152     边:(0,5) 权值:11
153     边:(1,8) 权值:12
154     边:(3,7) 权值:16
155     边:(1,6) 权值:16
156     边:(5,6) 权值:17
157     边:(1,2) 权值:18
158     边:(6,7) 权值:19
159     边:(3,4) 权值:20
160     边:(3,8) 权值:21
161     边:(2,3) 权值:22
162     边:(3,6) 权值:24
163     边:(4,5) 权值:26
164
165     打印最小生成树:
166     边(4,7) 权值:7
167     边(2,8) 权值:8
168     边(0,1) 权值:10
169     边(0,5) 权值:11
170     边(1,8) 权值:12
171     边(3,7) 权值:16
172     边(1,6) 权值:16
173     边(6,7) 权值:19
174     Press any key to continue
175 */
时间: 2024-11-08 00:43:39

克鲁斯卡尔(Kruskal)算法的相关文章

图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 B(G).其中 T(G)是遍历图时所经过的边的集合,B(G) 是遍历图时未经过的边的集合.显然,G1(V, T) 是图 G 的极小连通子图,即子图G1 是连通图 G 的生成树. 深度优先生成森林   右边的是深度优先生成森林: 连通图的生成树不一定是唯一的,不同的遍历图的方法得到不同的生成树;从不

图解最小生成树 - 克鲁斯卡尔(Kruskal)算法

我们在前面讲过的<克里姆算法>是以某个顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树的.同样的思路,我们也可以直接就以边为目标去构建,因为权值为边上,直接找最小权值的边来构建生成树也是很自然的想法,只不过构建时要考虑是否会形成环而已,此时我们就用到了图的存储结构中的边集数组结构,如图7-6-7 假设现在我们已经通过邻接矩阵得到了边集数组edges并按权值从小到大排列如上图. 下面我们对着程序和每一步循环的图示来看: 算法代码:(改编自<大话数据结构>) C++ Code 1

数据结构之---C语言实现最小生成树之kruskal(克鲁斯卡尔)算法

//Kruskal(克鲁斯卡尔)算法 //杨鑫 #include <stdio.h> #include <stdlib.h> #define MAX 1000 #define MAXE MAX #define MAXV MAX typedef struct { int beginvex1; //边的起始顶点 int endvex2; //边的终止顶点 int weight; //边的权值 }Edge; void kruskal(Edge E[],int n,int e) { int

最小生成树之Kruskal(克鲁斯卡尔)算法

克鲁斯卡尔算法:       是在剩下的所有未选取的边中,找最小边,如果和已选取的边构成回路,则放弃,选取次小边. 先构造一个只含 n 个顶点.而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集 E 中选取一条权值最小的边, 若该条边的两个顶点分属不同的树,则将其加入子图,即把两棵树合成一棵树,反之,若该条边的两个顶点已落在同一棵树上,则不可取, 而应该取下一条权值最小的边再试之.依次类推,直到森林中只有一棵树,也即子图中含有 n-1 条边为止. 时间复杂度为为O(e^2)

45. 蛤蟆的数据结构笔记之四十五克鲁斯卡尔算法

本篇名言:"假如生活欺骗了你 ,不要忧郁 , 也不要愤慨 !不顺心的时候暂且容忍 : 相信吧 , 快乐的日子就会到来.--普希金" 上两篇学习了弗洛伊德和迪杰特斯拉算法.这次来看下克鲁斯卡尔算法. 欢迎转载,转载请标明出处:http://write.blog.csdn.net/postedit/47071539 1.  克鲁斯卡尔算法 克鲁斯卡尔(Kruskal)算法是在剩下的所有未选取的边中,找最小边,如果和已选取的边构成回路,则放弃,选取次小边.是实现图的最小生成树最常用的算法.

克鲁斯卡尔算法与公交问题

克鲁斯卡尔算法与公交问题 应用场景-公交站问题 类似的 看一个应用场景和问题: 某城市新增7个站点(A, B, C, D, E, F, G) ,现在需要修路把7个站点连通 各个站点的距离用边线表示(权) ,比如 A – B 距离 12公里 问:如何修路保证各个站点都能连通,并且总的修建公路总里程最短? 克鲁斯卡尔算法介绍 克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法. 基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路 具体做法:首先构造一个只

Kruskal算法(三)之 Java详解

前面分别通过C和C++实现了克鲁斯卡尔,本文介绍克鲁斯卡尔的Java实现. 目录 1. 最小生成树 2. 克鲁斯卡尔算法介绍 3. 克鲁斯卡尔算法图解 4. 克鲁斯卡尔算法分析 5. 克鲁斯卡尔算法的代码说明 6. 克鲁斯卡尔算法的源码 转载请注明出处:http://www.cnblogs.com/skywang12345/ 更多内容:数据结构与算法系列 目录 最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的

Kruskal算法(一)之 C语言详解

最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树.  例如,对于如上图G4所示的连通网可以有多棵权值总和不相同的生成树. 克鲁斯卡尔算法介绍 克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法. 基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路. 具体做法:首先构造一个只含n个顶点的森林,然后依权值从小到大从连通网中选择边加入到森林中,并使森林中不产生

Kruskal算法(二)之 C++详解

本章是克鲁斯卡尔算法的C++实现. 目录 1. 最小生成树 2. 克鲁斯卡尔算法介绍 3. 克鲁斯卡尔算法图解 4. 克鲁斯卡尔算法分析 5. 克鲁斯卡尔算法的代码说明 6. 克鲁斯卡尔算法的源码 转载请注明出处:http://www.cnblogs.com/skywang12345/ 更多内容:数据结构与算法系列 目录 最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树. 例如,对于如上图G4所示的